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.
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.
Dashboardexamples/dashboard.py — oscilloscope · radar · hex waterfall · spirograph |
Stock Tickerexamples/stocks.py — live charts · sparklines · portfolio |
Doom Fireexamples/doom_fire.py — classic fire effect · half-block rendering |
IDEexamples/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/:
- Getting Started — install, first UI, first app.
- How It Works (Concepts) — the mental model: render pipeline, runtimes, performance, pitfalls.
- Text & Style —
T, markup helpers, colors. - Layout —
col,row,card,field,hr, options. - Apps — the
Appclass, key bindings, state, the view. - Widgets — 77 native renderers: charts, controls, agent UI, scrolling.
- Rendering —
show,to_string,animate,run. - Performance —
memo, the boundary tax, benchmarks. - API Reference — every public symbol.
- Low-Level API — primitives and the native binding.
- Distribution — standalone wheels for old machines.
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 positionedborder_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 like0.5,"auto", orpct(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))
Responsive layout: one number, re-solved on every resize
maya's responsive toolkit reshapes the UI from the width the terminal actually provides — no breakpoints, no width math:
from maya_py import grid, sidebar, fit_row, pick, clamp_width, show
# "Each cell wants ~26 columns": fits as many per row as the terminal
# allows, wraps the rest, stacks to one column when narrow.
show(grid([cpu_card, mem_card, net_card, disk_card], 26))
# Fixed-width rail + main pane; stacks vertically when too narrow.
show(sidebar(stats_panel, main_table, 42))
# A header that SHEDS detail as the terminal narrows — (el, keep) drops
# lowest-keep first; untagged items never drop.
show(fit_row(logo, (hostname, 5), (kernel, 4), (uptime, 2), gap=1))
# Semantic zoom: first alternative that fits wins; last is the fallback.
show(pick(rich_status, medium_status, icon_only))
# Cap prose width on an ultrawide and center it.
show(clamp_width(article, 100))
Plus place() (center a dialog / corner a toast), fit_col(), adapt() /
fill() (custom width- and slot-aware components), measure(), rainbow()
and gradient_rule() for pretty headings, and a paint-time mouse hit
registry (hit=hit_id(kind, i) on any box + hit_test(x, y)) so clicks
resolve against where the renderer actually painted — no hand-mirrored
layout math.
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)orrender(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.valueplumbing.@app.derive— installfn(state)as a read-only computed property on the state object. Works with the default state bag andmodel=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— theCanvasdrawing surface: lines, rects, a live plot.clock.py— a live analog clock drawn on theCanvas(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 toless -R).inline_progress.py— inlineprint+live(no alt-screen takeover).
Primitives & basics:
hello.pystatic card ·counter.py/stopwatch.py/todo.pyAppbasics ·paint.pymouse painter ·live_spinner.pyinline animation.counter_program.py/stopwatch_program.py— the pure MVUProgram(Elm Architecture): immutable model, pureupdate,Cmd/Subeffects, and a headless--testself-check.suspend.py—Cmd.suspend: hand the real terminal to an interactive child ($EDITOR / pager / shell), then restore the TUI and fold the child's exit code back into the model.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.execonsole works too (maya enablesENABLE_VIRTUAL_TERMINAL_PROCESSINGon 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.13 \
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.13/maya_py-0.2.13-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_28container, 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 thegcc-*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.13/maya_py-0.2.13.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().boxopts mirror maya'sBoxBuilder1: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, andwidth/height/min_*/max_*(each accepts an int,"50%","auto", or aDimension).component(fn, grow=..., width=..., height=...)— a lazy element whosefn(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'sScrollState+scrollbar_y/x).- Styles compose with
|:maya.bold | maya.fg(255, 128, 0), ormaya.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, examples/bench_live.py, and
examples/bench_vs_rich.py (30-row dashboard, this machine — yours will
differ):
Head-to-head vs Rich (the de-facto Python styled-output library — both
sides render identical content to a string, Rich via its idiomatic
Table/Text.assemble/Panel API with a pre-built Console):
| workload | maya-py | Rich | speedup |
|---|---|---|---|
| dashboard, 30 rows | ~82 µs | ~7.3 ms | ~89× |
| log flood, 200 lines | ~343 µs | ~12.8 ms | ~37× |
| data table, 100×6 | ~196 µs | ~25.7 ms | ~132× |
Geometric mean: ~76× faster than Rich — while doing real flexbox layout, wrapping, and a diffable frame Rich doesn't attempt.
Rendering to a string (one-shot output) vs a hand-tuned pure-Python ANSI string-concatenator (much faster than any real library — the honest lower bound):
| path | per render |
|---|---|
maya-py, friendly T(...) API |
~130 µs |
maya-py, rows() idiom |
~83 µs |
| bespoke pure-Python lower bound | ~70 µs |
The element build now flattens entirely in C++ — row()/col()/rows()
hand their raw children to a native spec engine that does the palette
lookups, tuple parsing and box construction in one crossing per container
(zero per-cell Python). That closed the build cost from ~99 µs to ~39 µs for
the rows() idiom; the bespoke concatenator is within ~20% and does no
layout at all.
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:
-
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-.boldapproach). -
Pass styled cells as tuples to skip the
Tobjects.row/colaccept(text, fg[, bg[, attrs]])tuple specs directly — the native spec engine flattens the whole container 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/tcolare kept as back-compat aliases; new code can just userow/col.) -
memocaches 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: the per-frame redraw — the thing that actually matters in a
terminal — renders the cached tree in ~26 µs vs ~70 µs for the bespoke
string-builder in examples/bench.py, while still doing real flexbox,
wrapping, and a partial-frame diff; and against a real library (Rich) the
full build+render pipeline is ~76× faster. memo + tuple-cell row/col +
rows() let the steady-state frame skip Python almost entirely.
License
MIT (same as maya).
Metadata
Release files for maya-py 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| maya_py-0.3.1.tar.gz | 13.6 MB | Details |
Built distributions (wheels)
Total release size: 66.7 MB
Release files / maya_py-0.3.1.tar.gz
| Download URL | maya_py-0.3.1.tar.gz |
|---|---|
| Size | 13.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b596d9268f9098dbd3b34f94ad8de934a24c05f4316187ee391ce00fbe7815a
|
|
BLAKE2b-256 checksum How to use checksums |
b54ebd2b8ba556c0d1431a60fce172421461526298d9bd63c8c9589528312a72
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp314-cp314-win_amd64.whl
| Download URL | maya_py-0.3.1-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c8de3fa44284c851ef720b5759d125972bb2a4bc0880f65855af328b18e81067
|
|
BLAKE2b-256 checksum How to use checksums |
1e4e8a28432a0b55fcdea76ecfa461e054582579d0c7f18c17e3c11317d4fe4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp314-cp314-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp314-cp314-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.14 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
ae8869d0edeba20a9fdbd5bf8f83aa2533eef3ab862de1602e34d0580a549cd3
|
|
BLAKE2b-256 checksum How to use checksums |
3529ccfebd0a9c5500e499381504bfae309c9306c60bf688c300ceb44db90d3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
fc41a9cf86d05bae761e30eab228182ca6b8905353945ac1e989a213ab1be00b
|
|
BLAKE2b-256 checksum How to use checksums |
5d34705bc6ff7dc1cf8d92cacfe8439450849d8496c239e8fa299d23f365bf1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp313-cp313-win_amd64.whl
| Download URL | maya_py-0.3.1-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
80658e9643cf801c4cbbdda7a83235f18d6d4c40d6019140c9ecc7b564d1d8b0
|
|
BLAKE2b-256 checksum How to use checksums |
36e9115f6318f811d17630a3a90ee128c3c0a76800c548b0925ee0b563cbb58e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp313-cp313-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp313-cp313-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
a62a767bf32364865bdc2161c35eef65ad6ee52a39cdb39cb6a718453e9693c8
|
|
BLAKE2b-256 checksum How to use checksums |
c45c74f204f988e3c1c0208fec955af9c17121cc7bdf08eebc64cffa7535ae44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4936b0aa423e79ee375dbbce361c449e0e7e094095eba2f17521009d854e713e
|
|
BLAKE2b-256 checksum How to use checksums |
db6e29eff037459bc85fec6e37b8654bb5b4df2522f414db8bc867adc8de119d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp312-cp312-win_amd64.whl
| Download URL | maya_py-0.3.1-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
494133535e8fca17c6d21a8cbe4893164853d864de6fa102338f9ff687764f50
|
|
BLAKE2b-256 checksum How to use checksums |
eef1d7d0f4c6e38af94b0b715988f172c28f66a109662fafcd8eec813dfb16c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp312-cp312-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp312-cp312-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.12 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
c479cddf42570fac55cccb860d943eacdb80c672a80ae2634e281e9996c23947
|
|
BLAKE2b-256 checksum How to use checksums |
88c807a2c20b4b93a0800934e52b69b62645ede1fa45895cbfc1bcc2b3e67a74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
451e963cdc3fb9cc7efb6da253f4d05295346d4ae5c4b5b6295a318d30f06a79
|
|
BLAKE2b-256 checksum How to use checksums |
59acfb22c8f3911a107a038e28018d65cf5dd7b58c3d71b7c01d464699bfbc6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp311-cp311-win_amd64.whl
| Download URL | maya_py-0.3.1-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
da37733bbe5d237a8bd2744541bc0cde887ac99c0d5224b12d5a11a295419d85
|
|
BLAKE2b-256 checksum How to use checksums |
d706a0fcb2a806b9b1aa34a06ef820c397a184b9cd265ad37be64fbf41227cd3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp311-cp311-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp311-cp311-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
e08ca315aa8f4f0a488ed8592a72a3fec97072630cb39d8fbfe25a6174b05c84
|
|
BLAKE2b-256 checksum How to use checksums |
1f2544155e2f52348bcda426fdf8192d65d845fe82f8c4ddce60b4994254a0e5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
0a117c53fb3312b15fa3133c0107ddeec1b2097d3ced5d35ed91a113da893e1e
|
|
BLAKE2b-256 checksum How to use checksums |
33e88dd183c9b19164b19061106ab5f96f7d9f7e681074225f3ed14afe0c96ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp310-cp310-win_amd64.whl
| Download URL | maya_py-0.3.1-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
82cdeeaa5979e796f7587dc56fa80a4961983466d53df1c4d04023d5af698e28
|
|
BLAKE2b-256 checksum How to use checksums |
09dbfaa80044666d1b640c985b16f95c0f58a956a2056476cd734886a2d5e520
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp310-cp310-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp310-cp310-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.10 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
73117502f1626c7de088a9737c4de67356088eb394918e72393ec13bb742566a
|
|
BLAKE2b-256 checksum How to use checksums |
d111a109d60c255be768a3829f3e1505774f7201c9d5d991b996e49d8f75f310
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9ff402ed6f4f4af3ea1692bbe124b99ae96447077696a9d09054db57c717f7ca
|
|
BLAKE2b-256 checksum How to use checksums |
be5d26650f807b742bef40a8de45038f186b65f506ef482e91ab4f5bea829d23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp39-cp39-win_amd64.whl
| Download URL | maya_py-0.3.1-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0971443174c0b2b98f87c59eea8275eeaf8f435448b760345b2c15d57aec1343
|
|
BLAKE2b-256 checksum How to use checksums |
17834b78ddc95daf5ac1639681d197e84f019b4ae8e29710bef3178cd01330fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp39-cp39-manylinux_2_28_x86_64.whl
| Download URL | maya_py-0.3.1-cp39-cp39-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
1c7939d3c26d067d099929df90a6fd7886a726e5c7d6b3d861515788b849fd68
|
|
BLAKE2b-256 checksum How to use checksums |
2d402a6eaa9d96dd2c310db9609c8eff3371f1026276cb2d6e9cf9c7c003e0b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency logRelease files / maya_py-0.3.1-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | maya_py-0.3.1-cp39-cp39-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.9 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f85b88d3b02d5269d25c6dfcc5d15d3673579584285a567fe7365b6f523d86b2
|
|
BLAKE2b-256 checksum How to use checksums |
131b411e641d98f87cbee9741ae7558efde7fa6929a716565364f2b9756e06b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 19, 2026.
Transparency log