Skip to content

Select and represent values ​

marimo_export.values holds the selector grammar used by every selected-value output and the media negotiation behind the media exporter. Hosts that read live notebook values use the same functions, so a selector, a figure, and a table render the same way in a live kernel and in an export that has the same libraries.

python
from marimo_export.values import Size, ValueSelector, represent

figure = ValueSelector("report.figure").resolve(globals())
pdf = represent(figure, ["application/pdf", "image/svg+xml"], size=Size(251.3))
assert pdf.media_type == "application/pdf"

rows = represent(ValueSelector("daily").resolve(globals()), ["application/json"])

The module imports only the Python standard library. A host can load its source where marimo-export is not installed, such as a Pyodide worker that runs a notebook in the browser.

ValueSelector ​

python
ValueSelector(source: str) -> ValueSelector
selector.resolve(namespace: Mapping[str, object]) -> object

ValueSelector(source) parses source into a frozen record with source, root, and path. Selectors with the same source are equal. Each path item is a SelectorStep(kind, key) named tuple, where kind is "attribute" or "item".

SyntaxStep
reportRoot: an ASCII identifier
.summaryAttribute: an identifier that does not start with _
[0]Item: a canonical integer from 0 through 2**53 - 1
["total value"]Item: a JSON string

A selector has no surrounding whitespace, contains at most MAX_SELECTOR_BYTES (4,096) UTF-8 bytes and MAX_SELECTOR_STEPS (64) steps, and must be well-formed Unicode. Other text raises SelectorError, a ValueError. OutputSpec factories report the same failure as SpecError with code spec_output_invalid.

resolve() reads the root from namespace, then applies each step. An attribute step reads a mapping key when the current value is a mapping that contains it, and the attribute otherwise. A step from None selects None, so peak.label reads as missing while peak is None. It raises LookupError when the root is undefined or a step is unavailable.

represent() ​

python
represent(
    value: object,
    accept: Iterable[str],
    *,
    scale: float = 1.0,
    size: Size | None = None,
) -> Representation

Returns a Representation for the first media type in accept that the value supports. Raises RepresentationError, a ValueError, when the value supports none of them. The message names the value's type, each display method that raised, and the package to install when a renderer is missing. Its reasons attribute holds those sentences without the type, for a host that names the value its own way.

Figures and charts use their library's renderer. A Vega-Lite specification is a mapping whose $schema is a https://vega.github.io/schema/vega-lite/ URL. Other values use the IPython display methods or marimo's _mime_() method, looked up on the value's type as Python looks up special methods. A display method that raises leaves its media types unavailable, and represent() tries the next accepted type.

ValueMedia types
Matplotlib figure or artistapplication/pdf, image/svg+xml, image/png
Altair chart or Vega-Lite specificationapplication/pdf, image/svg+xml, image/png with vl-convert-python
Value with _repr_mimebundle_()The types in its bundle
Value with _repr_*_()PNG, JPEG, SVG, PDF, HTML, Markdown, LaTeX, or JSON
Value with marimo's _mime_()The type it returns
Data, such as a table, list, or dateapplication/json, as described in JSON data

represent() passes IPython's include and exclude arguments to _repr_mimebundle_() when its signature takes them, and calls it without arguments otherwise, as marimo does. Data for a JSON media type can be any JSON value, such as an object, an array, a number, or a boolean.

A matplotlib artist, such as an Axes, renders its whole figure. Matplotlib PDF embeds TrueType fonts, which print preflight checks accept, and its PDF and SVG output omits creation dates and uses constant SVG element IDs, so equal figures produce equal bytes. An Altair chart renders with all of its rows, because the image carries no data. vl-convert-python draws charts with its bundled Vega-Lite release and embeds their fonts in PDF. It numbers those fonts in varying order, so the PDF bytes of equal charts can differ.

The notebook's own settings stay unchanged. A figure that marimo displays as a PNG can render as PDF for a typeset document and as SVG for a web page in the same session.

Size ​

python
Size(width: float | None = None, height: float | None = None) -> Size

A display size in points, 1/72 inch, such as the width of the column a document places a figure in or the height a slide row gives an image. Give a width, a height, or both. Size(251.3) sets the width, and Size(height=113.4) sets the height to 4 cm. represent() draws a copy of a matplotlib figure at that size, so its text keeps the point size the notebook gave it, and leaves the notebook's figure unchanged. The copy keeps the figure's layout engine, such as layout="constrained", or takes matplotlib's tight layout when the figure has none, without padding, so its labels fit inside the size, its ink reaches the page's edges, and the page has exactly that size. With only a width or only a height, the figure keeps its aspect ratio. A figure that Python cannot copy, such as one in a Pyodide runtime that holds an uncopyable counter, draws at its own size, and the consumer scales it.

A single or layered Vega-Lite chart draws at the size with autosize set to fit, so its axes and legends fit inside the size. With only a width, the chart keeps its own height, and with only a height, it keeps its own width. Compound charts and values drawn by display methods ignore the size.

Each length is a finite number from 1 to MAX_SIZE_POINTS (3,600, or 50 inches). Other numbers raise ValueError, and other types raise TypeError. A Size without a width or a height raises TypeError.

JSON data ​

A value without its own JSON display method represents as application/json when it is data:

ValueJSON
None, booleans, text, mappings with text keysThe same value
Lists, tuples, and dataclass instancesArrays, and objects keyed by field name
Integers up to 2**53 - 1, finite floats, DecimalNumbers, for a Decimal within the range of a float
NaN, and pandas and NumPy NaTnull
date, datetime, timeISO 8601 text, such as 2015-02-04T09:41:00+01:00
timedeltaSeconds
Enum memberIts value
NumPy scalar or arrayIts items, with datetimes read in microseconds
pandas, Polars, or PyArrow table with unique columnsA list of row objects keyed by column name
pandas or Polars series, PyArrow arrayA list of its items

A datetime keeps its wall time and offset. Each value and each object key counts toward MAX_JSON_VALUES (100,000), as in portable JSON. A larger JSON form raises RepresentationTooLarge, a RepresentationError, and a table or array fails that way before its items are read, so filter or aggregate it in the notebook. Infinite numbers, larger integers, mappings with other keys, and other objects have no JSON form, and RepresentationError names the part that failed, such as The item at ["total"] is infinite.OutputSpec.json() stores the same JSON form.

Representation ​

FieldTypeMeaning
media_typestrThe accepted media type, lowercased
databytesThe encoded value. Text media types use UTF-8
widthint | NoneDisplay width of a raster image in CSS pixels
heightint | NoneDisplay height of a raster image in CSS pixels

A matplotlib PNG displays at 100 CSS pixels per inch of figure size, as marimo shows figures whatever their DPI, and a chart PNG displays at the chart's size. scale multiplies the pixel density of the PNG images that represent() renders, and of rasterized artists inside a matplotlib PDF or SVG. A PNG rendered with scale=2 has twice as many pixels in each direction as its display size, so it stays sharp on a high-density screen.

Display methods can report a size through IPython metadata, such as {"width": 300} returned beside _repr_png_() data. Media without a reported size, including the PDF and SVG that represent() renders, leave both fields None. A Representation raises ValueError for a malformed media type or a size that is not a positive integer, and TypeError when data is not bytes. The media exporter stores the size in the BlobAsset metadata, and imageLoader() sizes the image element with it.

normalize_accept() ​

python
normalize_accept(accept: Iterable[str]) -> tuple[str, ...]

Returns the accepted media types lowercased and in preference order. Each entry is a type/subtype media type without parameters or wildcards. A list holds 1 to MAX_ACCEPTED_MEDIA_TYPES (32) unique entries, and reading stops at the first entry past that limit. A bare string raises TypeError, and an empty, duplicate, or malformed entry raises ValueError.

The media exporter applies represent() to a selected value in every exported state.

Released under the Apache 2.0 License.