Skip to main content

maya-py

Python bindings for maya — a C++26 TUI framework with flexbox layout, a SIMD cell-diff renderer, and an Elm-style runtime. maya-py gives you a dead-simple Python API for building styled terminal UIs and interactive apps.

3D FPS raycaster in a terminal — examples/fps.py

import maya_py as maya
from maya_py import card, field, b, hr

maya.show(card(
    b("maya-py").fg("sky"),
    hr(20),
    field("Status", "Online", value_color="green"),
    field("Region", "us-east-1"),
    title="service",
))

That's the whole program. Strings are UI — no manual element wrapping.

Gallery

Every demo below is a Python program under examples/ — run any of them with python examples/<name>.py.

Dashboard
examples/dashboard.py — oscilloscope · radar · hex waterfall · spirograph
Stock Ticker
examples/stocks.py — live charts · sparklines · portfolio
Doom Fire
examples/doom_fire.py — classic fire effect · half-block rendering
IDE
examples/ide.py — syntax highlighting · file tree · tabs

Plus a 3D raycaster, raymarcher, fluid sim, mandelbrot zoom, matrix rain, particle systems, spectrum analyzer, breakout, snake, and more — all under examples/.

Captures are from the shared maya engine; the maya-py examples drive the same renderer and produce identical frames.

Documentation

A full reference manual lives in docs/:

The 30-second tour

Text: just style strings

from maya_py import T, b, i, dim_text, c

b("bold")                 # bold
T("hi").bold.fg("sky")     # fluent chain
c("warn", "orange")        # colored
T("x").bg("red").fg("white")

Colors accept names ("red", "sky", "gold"), hex ("#ff8800", "#f80"), tuples ((255, 128, 0)), or ints (0xFF8800).

Layout: stacks that take bare strings

from maya_py import col, row, card, field, hr

col("top", "middle", "bottom")          # vertical
row("left", "right", gap=2)             # horizontal
card("body", title="hi", pad=1)          # bordered box
field("Name", "Ada")                     # "Name: Ada"
hr(40)                                   # horizontal rule

col / row / card accept the full maya flexbox surface as keywords:

  • box model: pad, margin, gap (int or 1/2/4-tuples)
  • border: border ("round"/"double"/"bold"/"dashed"/...), border_color, border_sides=sides(top=..., left=...), title, and positioned border_text=("Title", Top, Center) / border_text_end
  • sizing: width, height, min_width/max_width, min_height/max_height — each takes an int (cells), "50%", a float like 0.5, "auto", or pct(50)/cells(20)/auto()
  • flex: grow, shrink, basis, align, align_self, justify, wrap ("wrap"/"nowrap"/"reverse"), overflow ("hidden"/"scroll")
  • style: bg, fg, style=maya.style(...)

Full layout power

Everything maya C++ can express, the Python API can too:

from maya_py import T, col, row, card, center, stack, grow, component, pct, cells, sides

# percent widths + a flex child that fills the rest
row(
    card("nav", width=pct(30), title="sidebar"),
    grow(card("main content", title="body")),   # expands to fill
    gap=1,
)

# center anything in a region
center("ready", width=cells(20), height=5, border="round")

# z-stack: layers paint on top; the first sets the size
stack(card("  panel  ", height=6), T("NEW").fg("red").bold)

# partial borders
card("footer", border_sides=sides(top=True, right=False, bottom=False, left=False))

# a size-aware widget — render_fn(width, height) draws to fit its box
def bar(w, h):
    filled = int(w * 0.4)
    return T("█" * filled + "░" * (w - filled)).fg("green")
col("Loading", component(bar, height=1))

Widgets: maya's native renderers

maya ships a library of ready-made widgets — they render through the same C++ renderer maya uses, then drop straight into any layout:

from maya_py import col, row, sparkline, gauge, progress, badge, table, bar_chart

col(
    sparkline([3, 1, 4, 1, 5, 9, 2, 6], label="req/s", color="sky", show_last=True),
    gauge(0.72, "load", style="bar"),            # "arc" or "bar"
    progress(0.55, "build", width=24, fill="lime"),
    row(badge("PASS", kind="success"), badge("SKIP", kind="warning"), gap=1),
    table(["Name", ("Score", 0, "right")],       # (header, width, align)
          [["Ada", 99], ["Bob", 7]], bordered=True, title="top"),
    bar_chart([("jan", 4), ("feb", 9), ("mar", 6)]),
    gap=1,
)

Available — every color argument takes a name / (r,g,b) / "#rrggbb" / Color, same as everywhere else:

  • charts & meters: sparkline, gauge, progress, bar_chart, line_chart, heatmap, flame_chart, waterfall, activity_indicator
  • controls (rendered in any state — pass checked/on/selected/cursor): checkbox, toggle, radio, select, slider, button
  • text & labels: badge, divider, spinner, callout, status_banner, breadcrumb, tabs, gradient, link, title_chip, model_badge, file_ref, markdown, html, error_block
  • structure & nav: table, tree, list_view, menu, disclosure, key_help, calendar, timeline, picker (bordered command palette), modal, command_palette, log_viewer
  • agent UI: thinking, todo_list, toast, inline_diff, tool_call, plan_view, phase_chip, context_gauge, context_window, diff_view, git_graph, git_status, shortcut_row, system_banner, popup, overlay, user_message, assistant_message, activity_bar, file_changes, api_usage, cost_tracker, phase_accent, checkpoint_divider, turn_divider, streaming_cursor, token_stream, token_stream_sparkline, search_result, changes_strip, welcome_screen
  • graphics: image (1-bit braille), canvas (color half-block grid), Canvas (imperative drawing surface: set_pixel/line/rect/fill)
from maya_py import col, row, checkbox, slider, todo_list, timeline, tree

col(
    checkbox("Ship it", checked=True),
    slider(0.6, "volume", width=24, fill="sky"),
    todo_list([("design", "completed"), ("build", "in_progress"), "test"],
              description="sprint", status="running"),
    timeline([("clone", "", "0.4s", "completed"),
              ("compile", "", "", "in_progress", 8)]),
    tree({"label": "src", "expanded": True,
          "children": [{"label": "main.py"}, {"label": "util.py"}]}),
    gap=1,
)

List/tuple inputs are flexible: list items accept "str", (label, description, icon), or {...} dicts; timeline/todo statuses accept strings ("completed", "in_progress", ...) or the exported enums (TaskStatus, TodoItemStatus, ToastLevel, ButtonVariant, ToolCallKind, ToolCallStatus, PopupStyle, BannerLevel, FileChangeKind, TurnRole, CursorStyle, SearchKind, SearchStatus).

Scrolling: viewport + scrollbar

Clip tall/wide content to a window and pair it with a live scrollbar. Scrolling just works with no handler code — exactly like maya, the run loop auto-forwards ↑↓ / PgUp / PgDn / Home / End and the mouse wheel + scrollbar drag to every on-screen scroll state:

from maya_py import App, col, row, T, scroll_state, viewport, scrollbar

app = App("log", mouse=True)            # mouse=True for wheel + thumb drag
s = scroll_state()                      # auto-dispatch on (the maya default)
app.state(s=s)
content = col(*[T(f"line {i}") for i in range(200)])

@app.on("q", "esc")
def quit(st): app.stop()

@app.view
def view(st):
    return row(
        viewport(content, st.s, height=14, grow=1),   # 14-row window, fills width
        scrollbar(st.s, 14, style="neon", thumb_color="sky"),
        gap=1,
    )

app.run()

That's the whole thing — no scroll handler. viewport(content, state, width=, height=, grow=) clips + scrolls (0 on an axis = fill; grow=1 expands to fill its row/column so a sibling scrollbar pins to the edge). scrollbar(state, size, axis="y"|"x", style=, thumb_color=, track_color=) draws the bar; style is a preset name — line, block, slim, heavy, double, dotted, dashed, braille, ascii, shadow, minimal, neon, retro, danger, pixel. The ScrollState exposes x/y/max_x/max_y, scroll_by, scroll_to, scroll_to_top/bottom, at_top()/at_bottom(), and viewport_bounds (the painted rect, for click hit-testing).

Need custom routing (several independent scroll regions)? Set state.auto_dispatch = False and call scroll_handle(state, ev) yourself inside @app.on_key / @app.on_mouse. Don't do both — that double-scrolls.

Apps: a class with decorators, no event loop

from maya_py import App, card, b

app = App("counter", n=0, quit_keys=("q", "esc"))   # state + quit in the constructor

@app.on("+", "=")
def inc(s): s.n += 1

@app.on("-")
def dec(s): s.n -= 1

@app.view
def view(s):
    return card(b(f"Count: {s.n}").fg("sky"), title="counter")

app.run()

Key names: single chars ("q", "+"), "up"/"down"/"left"/"right", "enter", "esc", "space", "tab"/"shift+tab", "home"/"end", "pgup"/"pgdn", "insert"/"delete", "f1"–"f12", and modifier prefixes "ctrl+s", "alt+x", "shift+a". A typo'd key spec raises with a did-you-mean hint instead of silently never firing. Handlers get the state object; the view re-renders every frame.

Text input

Real interactive Input widgets — type into them, Tab between them, read .value. Register them with app.focus(...) and drop them in the view:

from maya_py import App, text_input, col

app = App("search")
query = text_input("type to filter…")
app.focus(query)

@app.view
def view(s):
    return col(query, f"searching: {query.value}")

app.run()

text_input(password=True) masks, textarea() is multi-line. @query.on_submit fires on Enter. An animation tick is @app.on_frame def tick(s, dt): ....

Declarative state: For, bind, @app.derive

The view is a pure function of state, so the whole UI reads top-to-bottom. Three helpers kill the last of the glue — list comprehensions, widget read-back, and recomputed fields:

from maya_py import App, text_input, card, col, For

app = App("cart", items=[("Pen", 2.0), ("Mug", 9.5)], name="")

# 1) @app.derive — a computed field, recomputed on access (no stale cache):
@app.derive
def total(s): return sum(price for _, price in s.items)

# 2) bind=(state, field) — the input mirrors a state field both ways, so the
#    view reads s.name directly and never touches widget.value:
name = text_input("your name…", bind=(app.s, "name"))
app.focus(name)

@app.view
def view(s):
    return card(
        # 3) For(...) maps a list into a box — like SwiftUI ForEach / JSX map.
        #    A two-param renderer gets (index, item) for free.
        For(s.items, lambda it: col(f"{it[0]}  ${it[1]:.2f}")),
        col("Name:", name, f"hello {s.name}"),
        f"Total: ${s.total:.2f}",
        title="cart",
    )

app.run()
  • For(items, render, *, into=col, empty=None, **opts) — map a sequence into a container. render(item) or render(index, item) (auto-detected). empty= shows a fallback when the list is empty.
  • text_input(..., bind=(state, "field")) — two-way binding: the field seeds the input and every keystroke writes back. No .value plumbing.
  • @app.derive — install fn(state) as a read-only computed property on the state object. Works with the default state bag and model= objects.

Mouse: clicks, scroll, drag

Decorate handlers for mouse input — registering any of them auto-enables mouse reporting (no mouse=True needed):

from maya_py import App, card

app = App("clicker")
app.state(hits=0, pos=(0, 0))

@app.on_click("left")          # "left" / "right" / "middle" / "any"
def click(s, col, row):        # col, row are 1-based screen cells
    s.hits += 1
    s.pos = (col, row)

@app.on_scroll
def scroll(s, direction):      # -1 up, +1 down
    s.hits += direction

@app.on_mouse
def any_mouse(s, ev):          # every mouse event (press/release/move/scroll)
    ...

@app.on("q", "esc")
def quit(s): app.stop()

@app.view
def view(s):
    return card(f"clicks {s.hits}  at {s.pos}", title="clicker")

app.run()

Low-level predicates work on any event too: mouse_clicked(ev, button), mouse_released(ev), mouse_moved(ev), scrolled_up/down(ev), mouse_pos(ev) -> (col, row) | None, mouse_button(ev), mouse_kind(ev), is_mouse(ev). Mouse needs a terminal that reports it (xterm, kitty, iTerm2, Windows Terminal, or tmux with set -g mouse on).

Animation

import maya_py as maya
from maya_py import animate, card

frames = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
n = 0
def render(dt):
    global n; n += 1
    return card(frames[n % len(frames)] + " working")
animate(render, fps=30)   # maya.quit() to stop

The Elm Architecture: Program (pure, testable, no mutation)

When you want the full discipline — an immutable Model, a closed set of Msg, a pure update, and side effects described as data — maya-py exposes maya's native MVU runtime as a Program. This is the same run<P> loop the C++ side uses, so the effects and subscriptions you return from Python are interpreted by maya's real runtime, not a reimplementation.

import maya_py as maya
from maya_py import Cmd, Sub, Program, card, T

class Counter(Program):
    title = "counter"

    def init(self):                       # -> model | (model, Cmd)
        return {"n": 0}, Cmd.set_title("counter")

    def update(self, m, msg):             # pure: no I/O, no mutation
        if msg == "inc":   return {**m, "n": m["n"] + 1}
        if msg == "dec":   return {**m, "n": m["n"] - 1}
        if msg == "quit":  return m, Cmd.quit()
        return m

    def view(self, m):                    # model -> Element
        return card(T(f"count: {m['n']}").bold)

    def subscribe(self, m):               # model -> event sources
        return Sub.on_key(lambda ev:
            "inc" if maya.key(ev, "+") else
            "dec" if maya.key(ev, "-") else
            "quit" if maya.key(ev, "q") else None)

Counter().run()

update never touches the terminal, so it stays a pure state transition you can unit-test in isolation. Effects are Cmd values — Cmd.quit(), Cmd.set_title(...), Cmd.after(ms, msg), Cmd.task(fn) (async work), Cmd.batch(...), clipboard + scrollback commands. Event sources are Sub values — Sub.on_key, Sub.on_mouse, Sub.on_resize, Sub.on_paste, Sub.every(ms, msg) (a timer), Sub.on_animation_frame(msg), Sub.batch(...). There's a plain-function form too: run_program(init, update, view, subscribe).

The whole architecture is headlessly testable. Because update is pure, Program.test() hands you a ProgramPilot that runs the real init/update/view with no terminal — you dispatch messages (exactly like elm-test), thread the immutable model, and assert on it and the rendered view:

p = Counter().test()
p.send("inc", "inc", "inc", "dec")        # dispatch messages in order
assert p.model == {"n": 2}
assert p.cmds                              # Cmd.set_title was emitted at init
assert "count: 2" in p.view_string(40)

Purity is enforced, not just encouraged. The pilot runs in strict mode by default: it snapshots the model before every update/view and raises ImpureUpdateError if a hook mutated it in place instead of returning a new one. So the moment someone writes the tempting m["n"] += 1; return m, their tests fail loudly with a pointer to the exact hook — the beautiful, pure architecture is the verified one, and the subtle stale-view bug never ships:

class Sloppy(Program):
    def update(self, m, msg):
        m["n"] += 1        # in-place mutation — the TEA sin
        return m
    ...

Sloppy().test().send("inc")   # raises ImpureUpdateError: update() mutated the
                              # model in place. Return a NEW model ({**m, ...}).

The check costs nothing at runtime (it lives in the test pilot), and there's an escape hatch — prog.test(strict=False) — for an intentionally huge or un-deep-copyable model.

See examples/counter_program.py and examples/stopwatch_program.py (the latter uses Sub.every timers, Sub.batch, and Cmd.batch, and ships a --test self-check that proves every transition with the pilot).

Examples

Every maya C++ example is ported 1:1 to Python — 34 of them, plus extras. Most are full apps you can drive; run any with PYTHONPATH=src python examples/NAME.py. A headless examples/smoke_all.py renders one frame of each (CI-friendly, no TTY needed).

Games & toys (half-block pixel rendering via examples/_halfblock.py):

  • snake.py — playable Snake (arrow keys / WASD).
  • breakout.py — Breakout/Arkanoid with bricks, comet trail, particles.
  • life.py — Conway's Game of Life with heat-aging palettes + patterns.
  • sorts.py — five sorting algorithms racing side by side.
  • maze.py — watch a maze carve itself (recursive backtracker) then a BFS flood-solve it; click to set the start cell, right-click the goal.

Graphics & sims (animate / App render loops):

  • doom_fire.py — the classic Doom fire effect, 3 palettes.
  • fluid.py — advection fluid / plasma with curl-noise velocity.
  • particles.py — a gravity particle fountain.
  • space.py — warp-speed starfield. space3d.py — rotating 3D wireframes.
  • raymarch.py — a real-time raymarched SDF scene (sphere + plane).
  • fps.py — a Wolfenstein-style textured raycaster with a minimap.
  • mandelbrot.py — a zooming coloured Mandelbrot. matrix.py — digital rain.
  • canvas.py — the Canvas drawing surface: lines, rects, a live plot.
  • clock.py — a live analog clock drawn on the Canvas (hands, ticks, arc).
  • gravity.py — an n-body gravity sandbox; mouse-hover crosshair, click to spawn an orbiting burst at the exact pixel.
  • boids.py — Reynolds flocking; the mouse leads or scatters the flock (precise, viewport-bounds hit-testing — no hardcoded offsets).

Dashboards & data:

  • dashboard.py — full-power layout (sidebar, z-stack, size-aware bars).
  • sysmon.py — live system monitor (sparklines, gauges, log feed).
  • stocks.py — stock ticker with sparklines + a gainers board.
  • spectrum.py — a faux audio spectrum analyzer. music.py — a player UI.
  • hacker.py — a "hollywood hacker" terminal of fake breaches.

Apps & agent UI:

  • deploy.py — a CI/CD pipeline dashboard with a live stage timeline.
  • chat.py — a chat client with bubbles + typing indicator.
  • messenger.py — multi-channel chat with unread badges + a composer.
  • ide.py — a VS Code / Zed-style mini IDE (tree, tabs, diagnostics, git).
  • agent.py / agent_session.py — Claude-Code-style agent sessions: thinking → tool cards → todo plan → streaming markdown answer.
  • widgets.py — one-shot widget showcase. widgets_gallery.py — live version.
  • markup.py — a GFM markdown render that flows into scrollback (pipe to less -R).
  • inline_progress.py — inline print + live (no alt-screen takeover).

Primitives & basics:

  • hello.py static card · counter.py / stopwatch.py / todo.py App basics · paint.py mouse painter · live_spinner.py inline animation.
  • counter_program.py / stopwatch_program.py — the pure MVU Program (Elm Architecture): immutable model, pure update, Cmd/Sub effects, and a headless --test self-check.
  • form.py — the declarative trio (For, bind=, @app.derive) in one cart.
  • scroll.py / scroll_clip.py / scroll_2d.py / scroll_slice.py / scroll_styles.py — every scrolling pattern (clip, two-axis, million-row slice, and all 15 scrollbar styles).

Run any of them:

PYTHONPATH=src python examples/agent_session.py

Install

The wheels are standalone — no compiler needed. maya-py ships precompiled binary wheels for CPython 3.9–3.14 on Linux (x86_64; aarch64 configured), Windows (x64), and macOS (Apple Silicon / arm64), so on a normal machine you just:

pip install maya-py

That's it — the wheel already contains the compiled extension, and pip picks the right one for your OS / architecture / Python automatically.

Then scaffold a runnable app and go:

maya new myapp     # writes myapp.py — a working counter app
python myapp.py    # run it (q / Esc to quit)

(maya new, maya demo, maya version also work as python -m maya_py ....)

Terminal note. maya speaks ANSI/VT escapes + truecolor + UTF-8. On Linux and macOS any modern terminal works. On Windows use Windows Terminal (the default on Windows 11; free on Windows 10) or any VT-capable host — the legacy cmd.exe console works too (maya enables ENABLE_VIRTUAL_TERMINAL_PROCESSING on startup), but Windows Terminal gives the best Unicode + color fidelity.

Installing straight from a GitHub Release (no PyPI)

If you'd rather not use PyPI (or want a specific build), install from the release assets. Let pip pick the right wheel for your Python:

pip install --find-links \
  https://github.com/1ay1/maya-py/releases/expanded_assets/v0.2.7 \
  maya-py

Or install a specific .whl by direct URL:

# e.g. CPython 3.13 on x86_64 Linux
pip install https://github.com/1ay1/maya-py/releases/download/v0.2.7/maya_py-0.2.7-cp313-cp313-manylinux_2_28_x86_64.whl

The Linux and macOS wheels work even on machines with a very old C++ toolchain (or none at all), because:

  • the wheel is built inside a manylinux_2_28 container, so it targets glibc 2.28 (2019) and runs on that-or-newer distros;
  • it statically links libstdc++/libgcc, so it doesn't need the host's (old) C++ runtime — it depends only on baseline libc/libm.

The Windows wheel links the UCRT present on every Windows 10+ machine. Nothing on your machine is compiled at install time, so your system compiler is irrelevant.

No matching wheel? Build from the sdist

If no prebuilt wheel matches your platform/Python, install the source distribution; this compiles the extension locally and needs a C++23-capable toolchain and CMake ≥ 3.28:

  • Linux: GCC ≥ 14 or Clang ≥ 18
  • macOS: Homebrew GCC (brew install gcc) — AppleClang is rejected (it misses C++23 library bits maya needs); CMake auto-picks the gcc-* driver
  • Windows: Visual Studio 2022 ≥ 17.10 (MSVC cl ≥ 19.40), "Desktop development with C++" workload
pip install \
  https://github.com/1ay1/maya-py/releases/download/v0.2.7/maya_py-0.2.7.tar.gz

The compile pulls maya in via CMake FetchContent and takes ~1–2 minutes (it builds maya from source). If your compiler is too old, the build aborts early with a clear, actionable message rather than a wall of template errors.

Development build

To hack on maya-py, build the extension in place (uses a sibling ../maya-src checkout if present, else clones maya):

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
cp build/_maya*.so src/maya_py/
PYTHONPATH=src python examples/hello.py

Wheels are produced by cibuildwheel via .github/workflows/wheels.yml — push a vX.Y.Z tag to build them and attach them to a GitHub Release automatically.

Low-level API

The friendly layer above is built on a thin primitive surface. You rarely need it, but it's there when you want raw control. box/text take explicit Style/Color objects:

maya.box(
    maya.text("Hello", maya.bold | maya.fg(255, 128, 0)),
    border=maya.Round, padding=1,
)
  • text(content, style=None, wrap=...), box(*children, **opts), vstack/hstack/zstack, center, blank(), nothing().
  • box opts mirror maya's BoxBuilder 1:1: direction, wrap, gap, padding, margin, border, border_color, border_sides, border_text, border_text_end, bg, fg, style, overflow, grow, shrink, basis, align, align_self, justify, and width/height/min_*/max_* (each accepts an int, "50%", "auto", or a Dimension).
  • component(fn, grow=..., width=..., height=...) — a lazy element whose fn(width, height) runs once layout allocates a size and returns the tree to fill it.
  • scroll_state(), viewport(content, state, width=, height=), scrollbar(state, size, axis=, style=), scroll_handle(state, ev) — the scrollable-window + scrollbar pair (maya's ScrollState + scrollbar_y/x).
  • Styles compose with |: maya.bold | maya.fg(255, 128, 0), or maya.style(fg=(80,220,120), bold=True).
  • render_to_string(element, width=80), print(element), live(render_fn, fps=30), run(event_fn, render_fn, ...).
  • Event predicates: key(ev, "q"), key_special(ev, SpecialKey.Up), ctrl(ev, "c"), alt(ev, "x"), any_key(ev), resized(ev).

Notes

maya's compile-time DSL (t<"...">, type-state pipes) is resolved by the C++ compiler and can't cross the Python boundary, so maya-py routes everything through maya's equivalent runtime builders. The element trees produced are identical — anything the DSL can express, the runtime API can too.

The widget functions wrap maya's own widget classes (Sparkline, Gauge, Table, ...) and return the Element they build, so what you see is maya's native rendering, not a Python reimplementation. Interactive controls that need maya's Program runtime + focus + signals (Input, TextArea, full List/Tree navigation) aren't wrapped — drive interactivity from the App class instead.

Performance

Honest numbers from examples/bench.py and examples/bench_live.py (30-row dashboard, this machine — yours will differ):

Rendering to a string (one-shot output). Here a tuned pure-Python renderer still edges ahead — building the element tree in Python and crossing pybind11 costs more than maya's native render saves:

path per render
maya-py (build + render) ~145 µs
pure-Python equivalent ~70 µs

~80% of maya-py's time is the Python tree construction + boundary crossing, not maya — the native render itself is only ~24 µs. So if you only render static output once, a pure-Python lib like Rich is still a touch faster (now ~2×, down from ~5×).

Live redraw to a terminal (what maya is built for). When you redraw a frame and only part changed, maya's SIMD cell-diff emits only the changed cells. A string renderer must re-emit the whole frame:

path bytes written / frame
maya-py (diff) ~112 B
re-emit whole frame ~1238 B

maya writes ~11× fewer bytes to the terminal. On a real tty — especially over SSH or a slow connection — bytes-on-wire is the bottleneck, and this is a decisive win. This is the scenario maya was designed for.

Making it fast

Three levers close most of the Python-side gap:

  1. Fluent styling is free. T("x").bold.fg("sky") accumulates state in pure Python and makes a single boundary crossing when the element is built (4.8× faster than the naive one-call-per-.bold approach).

  2. Pass styled cells as tuples to skip the T objects. row/col accept (text, fg[, bg[, attrs]]) tuple specs directly — in a hot redraw path (tables, lists, dashboards) the throwaway T per cell is the dominant build cost, and the tuple form flattens the whole row in one boundary crossing. Byte-identical output, same API:

    from maya_py import row, T, c, DIM
    
    # reads nicer for one-off UI:
    row(T(name).fg("sky"), c(status, color), T(latency).dim, gap=2)
    # faster (tuple cells, zero T allocations — use in per-frame loops):
    row((name, "sky"), (status, color), (latency, None, None, DIM), gap=2)
    

    You can mix both, and any built Element / nested box / component child transparently falls back to the general path — so row(sidebar, grow(main)) still works. (trow/tcol are kept as back-compat aliases; new code can just use row/col.)

  3. memo caches unchanged sub-trees. In a live app, wrap builders whose inputs rarely change — the hot frame then does no Python tree construction, just maya's native diff:

    from maya_py import memo, card, col, b
    
    @memo
    def header(title, count):     # rebuilt only when title/count change
        return card(b(title), f"{count} items")
    
    def view(s):
        return col(header(s.title, len(s.items)), body(s))
    

Bottom line: building a UI in Python always costs Python calls, but the thing that actually matters in a terminal — the per-frame redraw — is now faster than a hand-tuned pure-Python renderer: maya's native layout + paint renders the cached tree in ~25µs vs ~70µs for the bespoke string-builder in examples/bench.py, while still doing real flexbox, wrapping, and a partial-frame diff. memo + tuple-cell row/col let the steady-state frame skip Python almost entirely.

License

MIT (same as maya).

Metadata

Release files for maya-py 0.2.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for maya-py 0.2.10
File Size Uploaded
maya_py-0.2.10.tar.gz 13.5 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for maya-py 0.2.10
File
maya_py-0.2.10-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
maya_py-0.2.10-cp314-cp314-manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
maya_py-0.2.10-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
maya_py-0.2.10-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
maya_py-0.2.10-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
maya_py-0.2.10-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
maya_py-0.2.10-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
maya_py-0.2.10-cp311-cp311-manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
maya_py-0.2.10-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
maya_py-0.2.10-cp310-cp310-manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details
maya_py-0.2.10-cp39-cp39-win_amd64.whl CPython 3.9 CPython 3.9 Windows x86-64 Details
maya_py-0.2.10-cp39-cp39-manylinux_2_28_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.28+ x86-64 Details
maya_py-0.2.10-cp39-cp39-macosx_11_0_arm64.whl CPython 3.9 CPython 3.9 macOS 11.0+ ARM64 Details

Total release size: 59.6 MB

Release files / maya_py-0.2.10.tar.gz

Download URL maya_py-0.2.10.tar.gz
Size 13.5 MB
Tags Source
SHA-256 checksum
How to use checksums
1eb569bc2dc7f3a41bc35c4d6fe0cf163aa2192805b58d803b4c83bc49e63791
BLAKE2b-256 checksum
How to use checksums
3e41d9cd781e46f10403d7900a0478d30e8c92d5b2b72641c10ae9a629d91801
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp314-cp314-win_amd64.whl

Download URL maya_py-0.2.10-cp314-cp314-win_amd64.whl
Size 1.3 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
3a2e03b6f07d718c377e2595ba70fd1ba3c5c75580f6d2dabfd6021efc79c836
BLAKE2b-256 checksum
How to use checksums
5b6a57f4c76ba60b89a43bd6394c9c4b95e7e3eab6d21af29b9ae23a294980a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp314-cp314-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp314-cp314-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.14 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
17394fb58ed465e798d3284fcd1660dab6f2d1aba0f55ddd469cff3f033af023
BLAKE2b-256 checksum
How to use checksums
7cc956fac981025ae949167d6fa4e320e3d2ce5261c0000453b0a5a2e05bbf92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp314-cp314-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp314-cp314-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1043dd733bbdb4f830755fe2e485350b89c7ab723b45df6c047eaff19e14880d
BLAKE2b-256 checksum
How to use checksums
e6ae543bcf0732bfc63ee6c567403fa72585c2dd69af280c9bce0580ca1fbf77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp313-cp313-win_amd64.whl

Download URL maya_py-0.2.10-cp313-cp313-win_amd64.whl
Size 1.3 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
3ab52aa70c388724d2f51d6c3289b51bd9b1d674f9ff037c622f5337ab2a8ee8
BLAKE2b-256 checksum
How to use checksums
aeec8b5d00014743043384b77c2d15f03b13f107b373faab6d5cf872d1fda0dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp313-cp313-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ccbf069560a10c576a11b714ef0c3e08b5e98e7e326415190ac14a238f3dd557
BLAKE2b-256 checksum
How to use checksums
b028dbc3561f6b08f5adf98f82395b66a915b6238bf6e2bfe79b7c0bca9de763
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp313-cp313-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp313-cp313-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
2396bc742abca4f802829db0ae7364b1c4611fb5a44825320e7bd540c844af22
BLAKE2b-256 checksum
How to use checksums
3f0e504313d65892dac7ac5ecc1c740f08a8c4a82c5f27752def0e7c52cb1eac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp312-cp312-win_amd64.whl

Download URL maya_py-0.2.10-cp312-cp312-win_amd64.whl
Size 1.3 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
87c614dc1dae8706dbc574d56497d69f5997f207bb294aa6b1d06ff33eef142a
BLAKE2b-256 checksum
How to use checksums
8034b227c5bbde558640563f94b363437834001a92f22be312be4c9152ce3a56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp312-cp312-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
39bca2988bac798e24fb1c9cc388e616fdfc0b11c295f4f813218d090221d36a
BLAKE2b-256 checksum
How to use checksums
bed4e602a44e561233eccb9fbaa13f6aae3bd3e46a70b5f0872fd4de50166c60
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp312-cp312-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp312-cp312-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
789ee39b6a748479afe71af5a6dd770a524baf013e8545158b0c8a076f87cf9b
BLAKE2b-256 checksum
How to use checksums
d935dcaf29d621ebff2740f4eb93bad39a79b93f76ca4b342a206050e50c7b70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp311-cp311-win_amd64.whl

Download URL maya_py-0.2.10-cp311-cp311-win_amd64.whl
Size 1.3 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
d47f32c56985ccfb026115d1ef865cfb60dce1d101e8fa508196a131fd1ce599
BLAKE2b-256 checksum
How to use checksums
85df4def7a8c05239b8a1f78b86e7b87324c2720aedcff6c46505019b2ae1958
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp311-cp311-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp311-cp311-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d9211075fc8015fb162ad9895c272725970575ce875254b8f6c1ba61f005524f
BLAKE2b-256 checksum
How to use checksums
70fa0d1a92682f7b7f9db7bcf1cb364c71119ff43d59fbf4904cb38ba5d6460c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp311-cp311-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp311-cp311-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
72007bf6435bcce8018fcbc850772b2f7e11072edb89f07ff41206c6c514f74b
BLAKE2b-256 checksum
How to use checksums
cce8f3b7b0c5ea2e7b2b5582ef429c0abc7a7417e9c57105f9b6a3145a88acab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp310-cp310-win_amd64.whl

Download URL maya_py-0.2.10-cp310-cp310-win_amd64.whl
Size 1.3 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
1817536eb25d813769fe258bc630266ce3f4717b8e66f8809fdb07f6c952cf8e
BLAKE2b-256 checksum
How to use checksums
0e5b4b9081a6a79ee234c6d06cfb3f7b8664834320edea7d5363c10db89d296f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp310-cp310-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp310-cp310-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ca42762bd3dedf57d6667d78ecf3a2776f4b9b20c689300aea73f95472f0538e
BLAKE2b-256 checksum
How to use checksums
caa77724c4b13b8d20a854cdccc56494235af09920e3bd1e42165727765ca64c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp310-cp310-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp310-cp310-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
4de39012a91f272244072af5138d908bdc813254d1fe99cc77d0036ca7e2d009
BLAKE2b-256 checksum
How to use checksums
cceeb72b5bd4843f96d71ea704c1624e71d72ff4d0aec3c3700fded18510e8e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp39-cp39-win_amd64.whl

Download URL maya_py-0.2.10-cp39-cp39-win_amd64.whl
Size 1.3 MB
Tags CPython 3.9 Windows x86-64
SHA-256 checksum
How to use checksums
f2ae682bcb2b7e53a9bf3e25cede5500c7c07fdba988505cfdbcb6dd88292738
BLAKE2b-256 checksum
How to use checksums
6a7bf283e90e05bb3f8fb0e51451c424bacdd2116c45b3cfd25710ab4e1411af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp39-cp39-manylinux_2_28_x86_64.whl

Download URL maya_py-0.2.10-cp39-cp39-manylinux_2_28_x86_64.whl
Size 4.1 MB
Tags CPython 3.9 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
bb9a04a30f66cbcabe4b4251c02b95097d6daa250ed2f1d324522b837e73d435
BLAKE2b-256 checksum
How to use checksums
a8e1edd22cdcaadffb36a81d580ccd65f1ec49415d6d3626b6d76f8f922d2224
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release files / maya_py-0.2.10-cp39-cp39-macosx_11_0_arm64.whl

Download URL maya_py-0.2.10-cp39-cp39-macosx_11_0_arm64.whl
Size 2.3 MB
Tags CPython 3.9 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
310c60da8fc3838a8ced0f5f1a683effec81d3879169e826a5366b63407a122a
BLAKE2b-256 checksum
How to use checksums
282fabc6ff15f16ec4d75d2f2043c0056adb7e0e411f7ba78b1ca10957592c9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.1

19 release files

This release

0.2.10 This release

19 release files

0.2.9

19 release files

0.2.8

19 release files

0.2.7

19 release files

0.2.6

19 release files

0.2.5

13 release files

0.2.3

19 release files

0.2.2

19 release files

0.2.1

19 release files

0.2.0

19 release files

0.1.6

19 release files

0.1.5

19 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page