spyre2
Build interactive data web apps in pure Python — no HTML, CSS, or JavaScript required.
Spyre2 is a ground-up rewrite of spyre using a modern stack: FastAPI, Alpine.js, and native support for matplotlib, Plotly, and Altair.
Install
pip install spyre2
pip install spyre2[matplotlib] # + matplotlib
pip install spyre2[plotly] # + plotly
pip install spyre2[all] # everything
Quickstart
import numpy as np
import matplotlib.pyplot as plt
import spyre2
class SineApp(spyre2.App):
title = "Sine Wave"
inputs = [
spyre2.Slider("frequency", label="Frequency", min=1, max=20, default=5),
spyre2.Dropdown("color", label="Color",
options=["steelblue", "crimson", "seagreen"]),
]
outputs = [
spyre2.Plot("sine_plot"),
]
def sine_plot(self, frequency, color):
fig, ax = plt.subplots(figsize=(8, 4))
x = np.linspace(0, 2 * np.pi, 500)
ax.plot(x, np.sin(frequency * x), color=color)
return fig
SineApp().launch()
Open http://127.0.0.1:8000.
Inputs
| Class | Description |
|---|---|
Slider(id, min, max, step, default) |
Numeric range slider |
Dropdown(id, options, default) |
Select dropdown |
RadioButtons(id, options, default) |
Radio button group |
CheckboxGroup(id, options, default) |
Multi-select checkboxes |
TextInput(id, default, placeholder) |
Free-text input |
FileUpload(id, accept) |
File picker |
All inputs accept a label keyword argument. If omitted, the label is inferred from the id.
Outputs
| Class | Handler return type |
|---|---|
Plot(id) |
matplotlib.figure.Figure or plotly.Figure or altair.Chart |
Table(id) |
pandas.DataFrame |
HTML(id) |
str (HTML) |
Download(id) |
(filename: str, content: str | bytes) |
The handler method name must match the output id:
outputs = [spyre2.Plot("my_plot")]
def my_plot(self, **kwargs): # method name = output id
...
return fig
Layouts
Sidebar (default)
Controls on the left, outputs stacked on the right. No configuration needed.
Grid
from spyre2 import Layout
class MyApp(spyre2.App):
layout = Layout.grid([
["controls", "controls" ],
["plot_a", "plot_b" ],
["big_table", "big_table" ],
])
Repeat an ID across adjacent cells to span columns. "controls" is a reserved name for the input panel.
Tabs
layout = Layout.tabs({
"Overview": ["trend_plot"],
"Detail": ["data_table", "bar_chart"],
})
Multiple chart libraries
The chart library is detected automatically from the return type — no configuration needed.
# matplotlib
def my_plot(self, x):
fig, ax = plt.subplots()
ax.plot(...)
return fig # → rendered as SVG
# Plotly
import plotly.express as px
def my_plot(self, x):
return px.scatter(df, x="a", y="b") # → rendered via Plotly.js
# Altair
import altair as alt
def my_plot(self, x):
return alt.Chart(df).mark_line()... # → rendered via Vega-Embed
Jupyter notebooks
app.launch() detects when it's running inside a Jupyter kernel and automatically starts the server in a background thread and displays an inline IFrame.
SineApp().launch(port=8765) # displays inline in the notebook
Migrating from spyre v1
Use the included CLI tool to mechanically convert a v1 app:
spyre2-migrate myapp.py # preview conversion
spyre2-migrate myapp.py -o new.py # write to new file
spyre2-migrate myapp.py --in-place # overwrite (creates .bak backup)
The tool converts imports, inputs/outputs list-of-dicts, and renames getPlot/getTable etc., leaving # TODO comments where manual cleanup is needed.
What changes:
| spyre v1 | spyre2 |
|---|---|
from spyre import server |
import spyre2 |
class App(server.App) |
class App(spyre2.App) |
inputs = [{"type": "slider", "key": "x", ...}] |
inputs = [spyre2.Slider("x", ...)] |
def getPlot(self, params): x = params["freq"] |
def my_plot(self, freq): |
| CherryPy on port 9093 | uvicorn on port 8000 |
For apps that can't be fully migrated yet, spyre2.compat.App accepts the old dict-based syntax (deprecated, will be removed in a future release).
Examples
| File | Demonstrates |
|---|---|
examples/sine_example.py |
Sidebar layout, matplotlib, slider + dropdown |
examples/grid_example.py |
Grid layout, matplotlib, multiple outputs + table |
examples/plotly_example.py |
Tabs layout, Plotly, scatter + histogram |
Metadata
Release files for spyre2 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| spyre2-0.1.0.tar.gz | 108.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spyre2-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 150.4 kB
Release files / spyre2-0.1.0.tar.gz
| Download URL | spyre2-0.1.0.tar.gz |
|---|---|
| Size | 108.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f309f5ebaa55f6b2465cd06148e5ba0423abc87effe905bedc9c801231f98514
|
|
BLAKE2b-256 checksum How to use checksums |
9323631bccdc7d84fb2ab72b30984cafba7ac9bb2258bfc4fe3c87e2adfc9804
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / spyre2-0.1.0-py3-none-any.whl
| Download URL | spyre2-0.1.0-py3-none-any.whl |
|---|---|
| Size | 42.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec0925221d63f3115f3a11a7b27ddee18888a7def5f0aea1b0a7570eda5f10cf
|
|
BLAKE2b-256 checksum How to use checksums |
d92d4fdb6bf8cee4a086f7201434e645a17ee75fb718582ca99886b0b24e9d1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Security for spyre2 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.