VersoRelease

Verso 1.2: live widgets, panels, and five languages

A rendered widget keeps talking to the interpreter that drew it, a widget's value can become a shared variable any kernel reads, extensions can add panels beside the notebook, and the interface now speaks five languages.

Verso 1.2.1 is out. The thread running through it is connection: a widget that stays attached to its kernel, a widget value the other languages can read, and a panel an extension can put beside the notebook on any host.

What changed

Change What it does
Live Python widgets A rendered ipywidgets or anywidget control stays connected to the interpreter that made it
#!bind Projects a widget's trait into the shared variable store under a name you choose, both ways
DAG Notebook A showcase layout that reads which cells feed which and re-runs a cell's dependents
Notebook panels INotebookPanel and IPanelInteractionHandler, so an extension can add a panel beside the built-in five
Compare panel Steps through a notebook's changes one at a time while the notebook stays visible
Interface language German, Spanish, Japanese, and Simplified Chinese alongside English
Formatter extensions IExecutionContext.TryFormatAsync lets a package teach a kernel to render its own types
Native library resolution A package's own natives are preferred over a same-named library elsewhere on the machine

Widgets that are still connected

Drag a slider in a Python cell and the Python that made it hears about it, runs whatever the author wired to it, and can send something back, within a cell and across cells. That holds for ipywidgets and for anything built with anywidget, because Python cells run in a separate host process that is still there after the cell finishes.

A widget with no interpreter behind it, because you just opened the file or restarted its kernel, draws visibly inert with a note to run the cell. Saving asks each live widget for its state, so the file records what you were looking at rather than what the cell first drew.

Three ceilings apply, and each refuses with a diagnostic rather than going quiet: 4 MB for a widget's saved page, 8 MB for one message between a widget and its kernel, 1 MB for one projected value. The state travels in the notebook, but the JavaScript that draws it comes from a public CDN, so a machine with no network draws an empty frame.

A control in front of another language

#!bind takes a trait on any object in the Python interpreter and makes it an ordinary shared variable.

import ipywidgets as widgets

slider = widgets.IntSlider(value=20, min=0, max=100, description="Threshold")
slider
#!bind slider.value as threshold
var cutoff = Variables.Get<long>("threshold");
readings.Where(r => r > cutoff)
moving the slider writes the variable Python cell slider.value shared variables threshold C# cell Variables.Get writing the variable moves the slider a value settles after one round trip in whichever direction it started
A bound trait is an ordinary shared variable that happens to follow a control, and the control follows it back.

Variables.Set("threshold", 70L) from a C# cell moves the slider and fires the author's observe callbacks. #!bind --list shows every trait currently projected, and #!bind --remove <name> stops one following its widget without deleting the variable.

Two limits. A trait holding another widget is refused, layout and style being the ones people try first, so bind one of that widget's own traits instead. And a projection lasts as long as the interpreter: restart Python and the name keeps the value it last had, until you re-run the #!bind line.

Reactive execution, as a package

The new DAG Notebook showcase layout, published as Verso.Showcase.DagNotebook, scans each code cell for the variables it defines and the names it reads, draws chips linking producers to consumers, and runs a finished cell's dependents in dependency order. A bound control at the top of the graph cascades a run with nothing else clicked.

The scan is a heuristic rather than a proof, and the layout is honest about it: a variable written by more than one cell gets a warning chip and no edges, and cycle edges are excluded, so a cascade cannot loop. What I like most is that it is a package. Reactive execution is usually a property of the notebook tool you picked, and here it arrives as an extension.

Panels beside the notebook

An extension can now contribute a panel beside the notebook body by implementing INotebookPanel, toggled from the toolbar next to Verso's own Metadata, Extensions, Variables, Settings, and Cell Properties. A panel describes its content rather than drawing it, so it works on every host, including one that never touches a browser.

Five languages

The interface ships in German, Spanish, Japanese, and Simplified Chinese alongside English, covering the notebook UI, the toolbar and panels, the kernel messages that land in cell output, and the command line tool. Choose one with --language or the verso.language setting. With neither, Verso follows VERSO_LANGUAGE, then the operating system's language, then English. verso serve negotiates per browser from Accept-Language.

Numbers, dates, and currency keep the machine's own formatting whichever language you choose, because translating those would change what a cell computes.

From the community

A kernel can now hand a value to registered formatter extensions before its own rendering, through a new IExecutionContext.TryFormatAsync. PowerShell is the first kernel wired to it, contributed by @eosfor (#93), who also sent two PowerShell samples that build an automatic differentiation engine from scratch and run it on handwritten digits (#92).

Native libraries now resolve to a package's own copy in preference to a same-named library elsewhere on the system, and against the running process's architecture and C library rather than the machine's. That fixes a class of failure where a plotting library died on a version mismatch it had nothing to do with, found and diagnosed by @oxygen-dioxide (#91).

Upgrade notes

Code written after #!import in the same cell now runs. Everything below the directive used to be discarded silently, so a cell with boilerplate under an import will execute it for the first time on this release.

An extension built against Verso.Abstractions 1.2 needs a 1.2 or newer host. A host accepts an extension whose referenced minor version is at or below its own, and patch versions are never compared, which is why extensions kept loading across the 1.1 series.

Formatter extensions should check context.MimeType in CanFormat. Both new interface members have defaults, so nothing fails to compile, but a formatter that claims a value it cannot render in the requested MIME type is now stepped over.

Getting it

dotnet tool update -g Verso.Cli
code --install-extension Datafication.verso-notebook
dotnet add package Verso

The new Interactive Widgets guide covers #!bind and what separates a live widget from a static one, and Panels covers writing one. If a widget you rely on does not come back to life the way you expect, that is the report I want.