Skip to main content

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)

Source distribution for spyre2 0.1.0
File Size Uploaded Provenance
spyre2-0.1.0.tar.gz 108.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for spyre2 0.1.0
File Interpreter ABI Platform
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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