marimo
Advanced tools
| # Copyright 2026 Marimo. All rights reserved. | ||
| from __future__ import annotations | ||
| import threading | ||
| from typing import TYPE_CHECKING | ||
| if TYPE_CHECKING: | ||
| from marimo._output.hypertext import Html | ||
| class CellOutputList: | ||
| """Thread-safe container for a cell's imperatively constructed output.""" | ||
| def __init__(self) -> None: | ||
| self._items: list[Html] = [] | ||
| self._lock = threading.RLock() | ||
| def append(self, item: Html) -> None: | ||
| with self._lock: | ||
| self._items.append(item) | ||
| def clear(self) -> None: | ||
| with self._lock: | ||
| self._items.clear() | ||
| def replace_at_index(self, item: Html, idx: int) -> None: | ||
| with self._lock: | ||
| if idx > len(self._items): | ||
| raise IndexError( | ||
| f"idx is {idx}, must be <= {len(self._items)}" | ||
| ) | ||
| if idx == len(self._items): | ||
| self._items.append(item) | ||
| else: | ||
| self._items[idx] = item | ||
| def remove(self, value: object) -> None: | ||
| with self._lock: | ||
| self._items[:] = [ | ||
| item for item in self._items if item is not value | ||
| ] | ||
| def stack(self) -> Html | None: | ||
| """Return `vstack` of the items, or `None` if empty.""" | ||
| with self._lock: | ||
| if self._items: | ||
| from marimo._plugins.stateless.flex import vstack | ||
| return vstack(self._items) | ||
| return None | ||
| def __bool__(self) -> bool: | ||
| with self._lock: | ||
| return bool(self._items) | ||
| def __len__(self) -> int: | ||
| with self._lock: | ||
| return len(self._items) | ||
| def __repr__(self) -> str: | ||
| with self._lock: | ||
| return f"CellOutputList({self._items!r})" |
| # /// script | ||
| # requires-python = ">=3.11" | ||
| # dependencies = [ | ||
| # "marimo", | ||
| # ] | ||
| # /// | ||
| # Copyright 2026 Marimo. All rights reserved. | ||
| import marimo | ||
| __generated_with = "0.15.5" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import time | ||
| return mo, time | ||
| @app.cell | ||
| def _(mo): | ||
| sleep_time_radio = mo.ui.radio( | ||
| [".01", ".1", "1"], label="Sleep time", value=".01" | ||
| ) | ||
| sleep_time_radio | ||
| return (sleep_time_radio,) | ||
| @app.cell | ||
| def _(sleep_time_radio): | ||
| sleep_time = float(sleep_time_radio.value) | ||
| return (sleep_time,) | ||
| @app.cell | ||
| def _(mo): | ||
| disabled_switch = mo.ui.switch(label="Disable progress bar") | ||
| disabled_switch | ||
| return (disabled_switch,) | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| for _ in mo.status.progress_bar( | ||
| range(10), | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| for _ in mo.status.progress_bar( | ||
| range(10), | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| show_eta=True, | ||
| show_rate=True, | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| with mo.status.progress_bar( | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| total=10, | ||
| disabled=disabled_switch.value, | ||
| ) as bar: | ||
| for _ in range(10): | ||
| time.sleep(sleep_time) | ||
| bar.update() | ||
| return | ||
| @app.cell | ||
| def _(mo, sleep_time, time): | ||
| with mo.status.spinner(title="Loading...", remove_on_exit=True) as _spinner: | ||
| time.sleep(0.1) | ||
| _spinner.update("Almost done") | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(mo, sleep_time, time): | ||
| with mo.status.spinner(title="Loading...", remove_on_exit=True) as _spinner: | ||
| time.sleep(sleep_time) | ||
| _spinner.update("Almost done") | ||
| time.sleep(sleep_time) | ||
| mo.ui.table([1, 2, 3]) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| # Fast updates should be debounced for performance | ||
| for i in mo.status.progress_bar( | ||
| range(1000), | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time / 10) | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| import marimo | ||
| __generated_with = "0.20.1" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import time | ||
| import threading | ||
| return mo, threading, time | ||
| @app.cell | ||
| def _(mo, threading, time): | ||
| def append(): | ||
| for i in range(3): | ||
| mo.output.append(f"{i}: Hello from {threading.get_ident()}") | ||
| time.sleep(1) | ||
| return (append,) | ||
| @app.cell | ||
| def _(mo, threading, time): | ||
| def replace(): | ||
| for i in range(3): | ||
| mo.output.replace(f"{i}: Hello from {threading.get_ident()}") | ||
| time.sleep(1) | ||
| return (replace,) | ||
| @app.cell | ||
| def _(mo): | ||
| def run_threads(fn): | ||
| _threads = [mo.Thread(target=fn) for _ in range(3)] | ||
| for _t in _threads: | ||
| _t.start() | ||
| for _t in _threads: | ||
| _t.join() | ||
| return (run_threads,) | ||
| @app.cell | ||
| def _(append, run_threads): | ||
| run_threads(append) | ||
| return | ||
| @app.cell | ||
| def _(replace, run_threads): | ||
| run_threads(replace) | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| import marimo | ||
| __generated_with = "0.20.1" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import random | ||
| import time | ||
| import threading | ||
| return mo, random, threading, time | ||
| @app.cell | ||
| def _(mo, random, threading, time): | ||
| def step(pbar: mo.status.progress_bar, work: int): | ||
| for _ in range(work): | ||
| # Sleep... or anything else that releases GIL | ||
| time.sleep(random.uniform(0.5, 1)) | ||
| pbar.update( | ||
| subtitle=f"work completed by thread {threading.get_ident()}" | ||
| ) | ||
| return (step,) | ||
| @app.cell | ||
| def _(mo, random, step, time): | ||
| total = 30 | ||
| with mo.status.progress_bar(total=total) as pbar: | ||
| n_threads = 4 | ||
| work = total // n_threads | ||
| remainder = total % n_threads | ||
| threads = [ | ||
| mo.Thread(target=step, args=(pbar, work)) | ||
| for _ in range(n_threads) | ||
| ] | ||
| for t in threads: | ||
| t.start() | ||
| for t in threads: | ||
| t.join() | ||
| for _ in range(remainder): | ||
| time.sleep(random.uniform(0.5, 1)) | ||
| pbar.update(subtitle="work completed by main thread") | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| import marimo | ||
| __generated_with = "0.17.7" | ||
| app = marimo.App(width="medium") | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import random | ||
| return mo, random | ||
| @app.cell | ||
| def _(mo): | ||
| g, s = mo.state(0) | ||
| g(), s(1) | ||
| return g, s | ||
| @app.cell | ||
| def _(g, random): | ||
| g(), (x := random.randint(0, 10)) | ||
| return (x,) | ||
| @app.cell | ||
| def _(x): | ||
| x | ||
| return | ||
| @app.cell | ||
| def _(s): | ||
| s(6) | ||
| return | ||
| @app.cell | ||
| def _(mo): | ||
| def f(s): | ||
| import random | ||
| import time | ||
| thread = mo.current_thread() | ||
| while not thread.should_exit: | ||
| s(random.randint(0, 100000)) | ||
| time.sleep(1) | ||
| return (f,) | ||
| @app.cell | ||
| def _(f, mo, s): | ||
| mo.Thread(target=f, args=(s,)).start() | ||
| return | ||
| @app.cell | ||
| def _(g): | ||
| g() | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| import marimo | ||
| __generated_with = "0.15.5" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| return (mo,) | ||
| @app.function | ||
| def foo(): | ||
| print("hi") | ||
| @app.cell | ||
| def _(): | ||
| import threading | ||
| return (threading,) | ||
| @app.cell | ||
| def _(mo, threading): | ||
| with mo.redirect_stdout(): | ||
| threading.Thread(target=foo).start() | ||
| return | ||
| @app.cell | ||
| def _(mo): | ||
| with mo.redirect_stdout(): | ||
| mo.Thread(target=foo).start() | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
Sorry, the diff of this file is too big to display
| # Copyright 2026 Marimo. All rights reserved. | ||
| from __future__ import annotations | ||
| import threading | ||
| import time | ||
@@ -58,2 +59,3 @@ from collections.abc import AsyncIterable, Iterable, Sized | ||
| self.start_time = time.time() | ||
| self._lock = threading.Lock() | ||
| super().__init__(self._get_text()) | ||
@@ -67,3 +69,3 @@ | ||
| ) -> None: | ||
| """Update the progress indicator. | ||
| """Update the progress indicator. Thread-safe. | ||
@@ -88,14 +90,15 @@ Examples: | ||
| """ | ||
| if self.closed: | ||
| raise RuntimeError( | ||
| "Progress indicators cannot be updated after exiting " | ||
| "the context manager that created them. " | ||
| ) | ||
| self.current += increment | ||
| if title is not None: | ||
| self.title = title | ||
| if subtitle is not None: | ||
| self.subtitle = subtitle | ||
| with self._lock: | ||
| if self.closed: | ||
| raise RuntimeError( | ||
| "Progress indicators cannot be updated after exiting " | ||
| "the context manager that created them. " | ||
| ) | ||
| self.current += increment | ||
| if title is not None: | ||
| self.title = title | ||
| if subtitle is not None: | ||
| self.subtitle = subtitle | ||
| self._text = self._get_text() | ||
| self._text = self._get_text() | ||
| self.debounced_flush() | ||
@@ -102,0 +105,0 @@ |
@@ -138,3 +138,3 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| buf = io.BytesIO() | ||
| figure.savefig(buf, format="png") | ||
| figure.savefig(buf, format="png", dpi=figure.get_dpi(), bbox_inches=None) | ||
| buf.seek(0) | ||
@@ -208,14 +208,3 @@ encoded = base64.b64encode(buf.read()).decode("utf-8") | ||
| fig_width_px, fig_height_px = _figure_pixel_size(figure) | ||
| # Axes pixel bounds: [left, top, right, bottom] | ||
| # relative to the full figure image | ||
| bbox = axes.get_position() | ||
| axes_pixel_bounds: list[float] = [ | ||
| bbox.x0 * fig_width_px, # left | ||
| (1 - bbox.y1) * fig_height_px, # top | ||
| bbox.x1 * fig_width_px, # right | ||
| (1 - bbox.y0) * fig_height_px, # bottom | ||
| ] | ||
| # Validate scales first (fail fast, no side effects) | ||
| _SUPPORTED_SCALES = ("linear", "log") | ||
@@ -235,2 +224,16 @@ x_scale = axes.get_xscale() | ||
| # Render the figure first — savefig triggers the draw which | ||
| # finalizes layout (tight_layout, constrained_layout, etc.) | ||
| chart_base64 = _figure_to_base64(figure) | ||
| # Now capture axes position — reflects post-layout bounds | ||
| fig_width_px, fig_height_px = _figure_pixel_size(figure) | ||
| bbox = axes.get_position() | ||
| axes_pixel_bounds: list[float] = [ | ||
| bbox.x0 * fig_width_px, # left | ||
| (1 - bbox.y1) * fig_height_px, # top | ||
| bbox.x1 * fig_width_px, # right | ||
| (1 - bbox.y0) * fig_height_px, # bottom | ||
| ] | ||
| super().__init__( | ||
@@ -241,3 +244,3 @@ component_name=matplotlib.name, | ||
| args={ | ||
| "chart-base64": _figure_to_base64(figure), | ||
| "chart-base64": chart_base64, | ||
| "x-bounds": list(axes.get_xlim()), | ||
@@ -244,0 +247,0 @@ "y-bounds": list(axes.get_ylim()), |
@@ -93,11 +93,6 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| """Update the app's cached outputs.""" | ||
| from marimo._plugins.stateless.flex import vstack | ||
| del ctx | ||
| if ( | ||
| run_result.output is None | ||
| and run_result.accumulated_output is not None | ||
| ): | ||
| self.outputs[cell.cell_id] = vstack( | ||
| run_result.accumulated_output | ||
| if run_result.output is None and run_result.accumulated_output: | ||
| self.outputs[cell.cell_id] = ( | ||
| run_result.accumulated_output.stack() | ||
| ) | ||
@@ -104,0 +99,0 @@ else: |
@@ -12,3 +12,3 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| from contextlib import contextmanager | ||
| from dataclasses import dataclass | ||
| from dataclasses import dataclass, field | ||
| from typing import TYPE_CHECKING, Any, Optional | ||
@@ -18,2 +18,3 @@ | ||
| from marimo._messaging.context import HTTP_REQUEST_CTX | ||
| from marimo._runtime.cell_output_list import CellOutputList | ||
@@ -31,3 +32,2 @@ if TYPE_CHECKING: | ||
| from marimo._messaging.types import Stderr, Stdout, Stream | ||
| from marimo._output.hypertext import Html | ||
| from marimo._plugins.ui._core.registry import UIElementRegistry | ||
@@ -73,4 +73,4 @@ from marimo._runtime import dataflow | ||
| local_cell_id: Optional[CellId_t] = None | ||
| # output object set imperatively | ||
| output: Optional[list[Html]] = None | ||
| # outputs set imperatively via mo.output.append and associated functions | ||
| output: CellOutputList = field(default_factory=CellOutputList) | ||
| duckdb_connection: duckdb.DuckDBPyConnection | None = None | ||
@@ -77,0 +77,0 @@ |
@@ -9,3 +9,2 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| from marimo._output.rich_help import mddoc | ||
| from marimo._plugins.stateless.flex import vstack | ||
| from marimo._runtime.context import get_context | ||
@@ -46,6 +45,7 @@ from marimo._runtime.context.types import ContextNotInitializedError | ||
| return | ||
| elif value is None: | ||
| ctx.execution_context.output = None | ||
| else: | ||
| ctx.execution_context.output = [formatting.as_html(value)] | ||
| output = ctx.execution_context.output | ||
| output.clear() | ||
| if value is not None: | ||
| output.append(formatting.as_html(value)) | ||
| write_internal(cell_id=ctx.execution_context.cell_id, value=value) | ||
@@ -71,15 +71,10 @@ | ||
| if ctx.execution_context is None or ctx.execution_context.output is None: | ||
| if ctx.execution_context is None: | ||
| return | ||
| elif idx > len(ctx.execution_context.output): | ||
| raise IndexError( | ||
| f"idx is {idx}, must be <= {len(ctx.execution_context.output)}" | ||
| ) | ||
| elif idx == len(ctx.execution_context.output): | ||
| ctx.execution_context.output.append(formatting.as_html(value)) | ||
| else: | ||
| ctx.execution_context.output[idx] = formatting.as_html(value) | ||
| output = ctx.execution_context.output | ||
| output.replace_at_index(formatting.as_html(value), idx) | ||
| write_internal( | ||
| cell_id=ctx.execution_context.cell_id, | ||
| value=vstack(ctx.execution_context.output), | ||
| value=output.stack(), | ||
| ) | ||
@@ -106,9 +101,7 @@ | ||
| if ctx.execution_context.output is None: | ||
| ctx.execution_context.output = [formatting.as_html(value)] | ||
| else: | ||
| ctx.execution_context.output.append(formatting.as_html(value)) | ||
| output = ctx.execution_context.output | ||
| output.append(formatting.as_html(value)) | ||
| write_internal( | ||
| cell_id=ctx.execution_context.cell_id, | ||
| value=vstack(ctx.execution_context.output), | ||
| value=output.stack(), | ||
| ) | ||
@@ -133,7 +126,4 @@ | ||
| if ctx.execution_context.output is not None: | ||
| value = vstack(ctx.execution_context.output) | ||
| else: | ||
| value = None | ||
| write_internal(cell_id=ctx.execution_context.cell_id, value=value) | ||
| output = ctx.execution_context.output | ||
| write_internal(cell_id=ctx.execution_context.cell_id, value=output.stack()) | ||
@@ -148,8 +138,6 @@ | ||
| if ctx.execution_context is None or ctx.execution_context.output is None: | ||
| if ctx.execution_context is None or not ctx.execution_context.output: | ||
| return | ||
| output = [ | ||
| item for item in ctx.execution_context.output if item is not value | ||
| ] | ||
| ctx.execution_context.output = output if output else None | ||
| output = ctx.execution_context.output | ||
| output.remove(value) | ||
| flush() |
@@ -331,6 +331,6 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| # 1. if run_result.output is not None, need to send it | ||
| # 2. otherwise if exc_ctx.output is None, then need to send | ||
| # 2. otherwise if accumulated_output is empty, then need to send | ||
| # the (empty) output (to clear it) | ||
| should_send_output = ( | ||
| run_result.output is not None or run_result.accumulated_output is None | ||
| run_result.output is not None or not run_result.accumulated_output | ||
| ) | ||
@@ -337,0 +337,0 @@ if ( |
@@ -10,2 +10,3 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| from marimo._runtime.cell_lifecycle_item import CellLifecycleItem | ||
| from marimo._runtime.cell_output_list import CellOutputList | ||
| from marimo._runtime.context.kernel_context import KernelRuntimeContext | ||
@@ -151,2 +152,10 @@ from marimo._runtime.context.script_context import ScriptRuntimeContext | ||
| pass | ||
| output = CellOutputList() | ||
| if self._marimo_ctx is not None: | ||
| if (exec_ctx := self._marimo_ctx.execution_context) is not None: | ||
| # Share the parent's CellOutputList so appends from threads | ||
| # are visible to the main execution context. | ||
| output = exec_ctx.output | ||
| if isinstance(self._marimo_ctx, KernelRuntimeContext): | ||
@@ -156,2 +165,3 @@ self._marimo_ctx.execution_context = ExecutionContext( | ||
| setting_element_value=False, | ||
| output=output, | ||
| ) | ||
@@ -158,0 +168,0 @@ thread_id = threading.get_ident() |
@@ -5,3 +5,3 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| __generated_with = "0.15.5" | ||
| __generated_with = "0.20.1" | ||
| app = marimo.App() | ||
@@ -13,2 +13,3 @@ | ||
| import marimo as mo | ||
| return (mo,) | ||
@@ -20,2 +21,3 @@ | ||
| import time | ||
| return (time,) | ||
@@ -35,2 +37,3 @@ | ||
| time.sleep(.01) | ||
| return loop_append, loop_replace | ||
@@ -41,3 +44,5 @@ | ||
| def _(mo): | ||
| mo.md("""### Replace""") | ||
| mo.md(""" | ||
| ### Replace | ||
| """) | ||
| return | ||
@@ -62,3 +67,5 @@ | ||
| def _(mo): | ||
| mo.md("""### Append""") | ||
| mo.md(""" | ||
| ### Append | ||
| """) | ||
| return | ||
@@ -83,3 +90,5 @@ | ||
| def _(mo): | ||
| mo.md("""### Clear""") | ||
| mo.md(""" | ||
| ### Clear | ||
| """) | ||
| return | ||
@@ -106,3 +115,5 @@ | ||
| def _(mo): | ||
| mo.md("""### Sleep (stale)""") | ||
| mo.md(""" | ||
| ### Sleep (stale) | ||
| """) | ||
| return | ||
@@ -109,0 +120,0 @@ |
| import marimo | ||
| __generated_with = "0.19.11" | ||
| __generated_with = "0.20.1" | ||
| app = marimo.App() | ||
@@ -42,12 +42,8 @@ | ||
| @app.cell | ||
| def _(embedding, mnist, plt): | ||
| def _(embedding, mnist, plt, pymde): | ||
| x = embedding[:, 0] | ||
| y = embedding[:, 1] | ||
| plt.scatter(x=x, y=y, s=0.05, cmap="Spectral", c=mnist.attributes["digits"]) | ||
| plt.yticks([-2, 0, 2]) | ||
| plt.xticks([-2, 0, 2]) | ||
| plt.ylim(-2.5, 2.5) | ||
| plt.xlim(-2.5, 2.5) | ||
| ax = plt.gca() | ||
| ax = pymde.plot(X=embedding, color_by=mnist.attributes["digits"]) | ||
| plt.tight_layout() | ||
| return ax, x, y | ||
@@ -78,2 +74,67 @@ | ||
| mo.md(""" | ||
| ## Edge-data test | ||
| Points are clustered right at the axes edges. Clicking on tick labels, | ||
| axis labels, or the title should **not** start a selection. Previously | ||
| the click was clamped to the nearest edge, which would select these | ||
| edge points via `get_mask()`. | ||
| """) | ||
| return | ||
| @app.cell | ||
| def _(np, plt): | ||
| rng = np.random.default_rng(99) | ||
| # Points hugging the four edges of [0, 10] x [0, 10] | ||
| edge_n = 30 | ||
| edge_x = np.concatenate([ | ||
| rng.uniform(0, 0.3, edge_n), # left edge | ||
| rng.uniform(9.7, 10, edge_n), # right edge | ||
| rng.uniform(0, 10, edge_n), # bottom edge | ||
| rng.uniform(0, 10, edge_n), # top edge | ||
| rng.uniform(3, 7, edge_n), # centre (control) | ||
| ]) | ||
| edge_y = np.concatenate([ | ||
| rng.uniform(0, 10, edge_n), # left edge | ||
| rng.uniform(0, 10, edge_n), # right edge | ||
| rng.uniform(0, 0.3, edge_n), # bottom edge | ||
| rng.uniform(9.7, 10, edge_n), # top edge | ||
| rng.uniform(3, 7, edge_n), # centre (control) | ||
| ]) | ||
| plt.figure() | ||
| plt.scatter(edge_x, edge_y, s=20, c=edge_y, cmap="viridis") | ||
| plt.colorbar(label="y value") | ||
| plt.xlim(0, 10) | ||
| plt.ylim(0, 10) | ||
| plt.xlabel("X axis (click here should NOT select)") | ||
| plt.ylabel("Y axis (click here should NOT select)") | ||
| plt.title("Title area (click here should NOT select)") | ||
| edge_ax = plt.gca() | ||
| return edge_ax, edge_x, edge_y | ||
| @app.cell | ||
| def _(edge_ax, mo): | ||
| edge_fig = mo.ui.matplotlib(edge_ax) | ||
| edge_fig | ||
| return (edge_fig,) | ||
| @app.cell | ||
| def _(edge_fig, edge_x, edge_y): | ||
| _m = edge_fig.value.get_mask(edge_x, edge_y) | ||
| f"Selected {_m.sum()} / {len(edge_x)} points" | ||
| return | ||
| @app.cell | ||
| def _(edge_fig): | ||
| edge_fig.value if edge_fig.value else "No selection!" | ||
| return | ||
| @app.cell(hide_code=True) | ||
| def _(mo): | ||
| mo.md(""" | ||
| ## Log-scale axes test | ||
@@ -80,0 +141,0 @@ """) |
@@ -69,3 +69,3 @@ <!DOCTYPE html> | ||
| <title>{{ title }}</title> | ||
| <script type="module" crossorigin src="./assets/index-DEPjuBkG.js"></script> | ||
| <script type="module" crossorigin src="./assets/index-xckvhXGM.js"></script> | ||
| <link rel="modulepreload" crossorigin href="./assets/preload-helper-reX6CfMN.js"> | ||
@@ -72,0 +72,0 @@ <link rel="modulepreload" crossorigin href="./assets/clsx-nlQpVU_5.js"> |
@@ -142,6 +142,6 @@ # Copyright 2026 Marimo. All rights reserved. | ||
| mo.md(r""" | ||
| /// Tip | "Data sources panel" | ||
| /// Tip | "Variables panel" | ||
| Click the database "barrel" icon in the left toolbar to see all dataframes and in- | ||
| memory tables that your notebook has access to. | ||
| Open the variables panel in the left toolbar to see all dataframes | ||
| and in-memory tables that your notebook has access to. | ||
| /// | ||
@@ -148,0 +148,0 @@ """) |
+1
-1
| Metadata-Version: 2.3 | ||
| Name: marimo | ||
| Version: 0.20.1 | ||
| Version: 0.20.2 | ||
| Summary: A library for making reactive notebooks and apps | ||
@@ -5,0 +5,0 @@ License: |
+1
-1
@@ -7,3 +7,3 @@ [build-system] | ||
| name = "marimo" | ||
| version = "0.20.1" | ||
| version = "0.20.2" | ||
| description = "A library for making reactive notebooks and apps" | ||
@@ -10,0 +10,0 @@ # We try to keep dependencies to a minimum, to avoid conflicts with |
| import marimo | ||
| __generated_with = "0.17.7" | ||
| app = marimo.App(width="medium") | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import random | ||
| return mo, random | ||
| @app.cell | ||
| def _(mo): | ||
| g, s = mo.state(0) | ||
| g(), s(1) | ||
| return g, s | ||
| @app.cell | ||
| def _(g, random): | ||
| g(), (x := random.randint(0, 10)) | ||
| return (x,) | ||
| @app.cell | ||
| def _(x): | ||
| x | ||
| return | ||
| @app.cell | ||
| def _(s): | ||
| s(6) | ||
| return | ||
| @app.cell | ||
| def _(mo): | ||
| def f(s): | ||
| import random | ||
| import time | ||
| thread = mo.current_thread() | ||
| while not thread.should_exit: | ||
| s(random.randint(0, 100000)) | ||
| time.sleep(1) | ||
| return (f,) | ||
| @app.cell | ||
| def _(f, mo, s): | ||
| mo.Thread(target=f, args=(s,)).start() | ||
| return | ||
| @app.cell | ||
| def _(g): | ||
| g() | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| # /// script | ||
| # requires-python = ">=3.11" | ||
| # dependencies = [ | ||
| # "marimo", | ||
| # ] | ||
| # /// | ||
| # Copyright 2026 Marimo. All rights reserved. | ||
| import marimo | ||
| __generated_with = "0.15.5" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| import time | ||
| return mo, time | ||
| @app.cell | ||
| def _(mo): | ||
| sleep_time_radio = mo.ui.radio( | ||
| [".01", ".1", "1"], label="Sleep time", value=".01" | ||
| ) | ||
| sleep_time_radio | ||
| return (sleep_time_radio,) | ||
| @app.cell | ||
| def _(sleep_time_radio): | ||
| sleep_time = float(sleep_time_radio.value) | ||
| return (sleep_time,) | ||
| @app.cell | ||
| def _(mo): | ||
| disabled_switch = mo.ui.switch(label="Disable progress bar") | ||
| disabled_switch | ||
| return (disabled_switch,) | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| for _ in mo.status.progress_bar( | ||
| range(10), | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| for _ in mo.status.progress_bar( | ||
| range(10), | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| show_eta=True, | ||
| show_rate=True, | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| with mo.status.progress_bar( | ||
| title="Loading", | ||
| subtitle="Please wait", | ||
| total=10, | ||
| disabled=disabled_switch.value, | ||
| ) as bar: | ||
| for _ in range(10): | ||
| time.sleep(sleep_time) | ||
| bar.update() | ||
| return | ||
| @app.cell | ||
| def _(mo, sleep_time, time): | ||
| with mo.status.spinner(title="Loading...", remove_on_exit=True) as _spinner: | ||
| time.sleep(0.1) | ||
| _spinner.update("Almost done") | ||
| time.sleep(sleep_time) | ||
| return | ||
| @app.cell | ||
| def _(mo, sleep_time, time): | ||
| with mo.status.spinner(title="Loading...", remove_on_exit=True) as _spinner: | ||
| time.sleep(sleep_time) | ||
| _spinner.update("Almost done") | ||
| time.sleep(sleep_time) | ||
| mo.ui.table([1, 2, 3]) | ||
| return | ||
| @app.cell | ||
| def _(disabled_switch, mo, sleep_time, time): | ||
| # Fast updates should be debounced for performance | ||
| for i in mo.status.progress_bar( | ||
| range(1000), | ||
| disabled=disabled_switch.value, | ||
| ): | ||
| time.sleep(sleep_time / 10) | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
| import marimo | ||
| __generated_with = "0.15.5" | ||
| app = marimo.App() | ||
| @app.cell | ||
| def _(): | ||
| import marimo as mo | ||
| return (mo,) | ||
| @app.function | ||
| def foo(): | ||
| print("hi") | ||
| @app.cell | ||
| def _(): | ||
| import threading | ||
| return (threading,) | ||
| @app.cell | ||
| def _(mo, threading): | ||
| with mo.redirect_stdout(): | ||
| threading.Thread(target=foo).start() | ||
| return | ||
| @app.cell | ||
| def _(mo): | ||
| with mo.redirect_stdout(): | ||
| mo.Thread(target=foo).start() | ||
| return | ||
| if __name__ == "__main__": | ||
| app.run() |
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
116418690
0.01%1860
0.16%201821
0.09%