Skip to main content

spaday-perspective

Perspective for spaday

Build Status codecov License PyPI

Overview

spaday-perspective moves the existing PerspectivePanel integration out of spaday core. Its self-contained <perspective-panel> bundle includes Perspective's client, viewer, workspace, datagrid, themes, and viewer WASM.

Documentation

Quick example

This complete app serves a live Perspective table. Add trade streams a new row into the grid, the select switches between flat and grouped layouts, and the checkbox changes the viewer theme.

import perspective
from perspective.handlers.starlette import PerspectiveStarletteHandler
from starlette.responses import JSONResponse
from starlette.routing import Route, WebSocketRoute
from starlette.websockets import WebSocket

from spaday import CallEndpoint, cond, element, eq, field, obj
from spaday.backends.starlette import serve
from spaday_perspective import PerspectivePanel

server = perspective.Server()
client = server.new_local_client()
trades = client.table(
    [
        {"id": 1, "symbol": "AAPL", "side": "buy", "price": 211.10},
        {"id": 2, "symbol": "MSFT", "side": "sell", "price": 503.02},
    ],
    name="trades",
)
next_id = 2


async def add_trade(_request):
    global next_id
    next_id += 1
    trades.update(
        [
            {
                "id": next_id,
                "symbol": "AAPL" if next_id % 2 else "MSFT",
                "side": "buy" if next_id % 2 else "sell",
                "price": 210 + next_id,
            }
        ]
    )
    return JSONResponse({"id": next_id})


async def perspective_socket(websocket: WebSocket):
    await PerspectiveStarletteHandler(perspective_server=server, websocket=websocket).run()


def layout(*, grouped=False):
    viewer = {"table": "trades", "plugin": "Datagrid", "columns": ["symbol", "side", "price"]}
    if grouped:
        viewer.update({"group_by": ["symbol"], "columns": ["price"], "aggregates": {"price": "avg"}})
    return {
        "sizes": [1],
        "detail": {"main": {"type": "tab-area", "widgets": ["trades"], "currentIndex": 0}},
        "master": {"sizes": [], "widgets": []},
        "mode": "globalFilters",
        "viewers": {"trades": viewer},
    }


panel = (
    PerspectivePanel()
    .compute("theme", cond(field("dark"), "dark", "light"))
    .compute(
        "config",
        obj(
            {
                "ws_url": "/perspective",
                "tables": ["trades"],
                "layout": cond(eq(field("view"), "grouped"), layout(grouped=True), layout()),
            }
        ),
    )
    .style(display="block", height="70vh", margin_top="1rem")
)

view = element("select").bind("value", "view", mode="two-way").child(
    element("option", "Blotter", value="blotter"),
    element("option", "Average by symbol", value="grouped"),
)
dark = element("input", type="checkbox").bind("checked", "dark", mode="two-way")
page = (
    element("main")
    .style(margin="1rem", font_family="system-ui")
    .child(element("button").text("Add trade").on("click", CallEndpoint("POST", "/api/trades")))
    .child(view)
    .child(element("label").child(dark, " Dark theme"))
    .child(panel)
)

app = serve(
    page,
    packages=["perspective"],
    store={"view": "blotter", "dark": False},
    routes=[
        Route("/api/trades", add_trade, methods=["POST"]),
        WebSocketRoute("/perspective", perspective_socket),
    ],
)

Save this as app.py, then run pip install spaday-perspective perspective-python starlette uvicorn and uvicorn app:app. Open http://127.0.0.1:8000.

This keeps Perspective's bulk data on its native websocket. A spaday/transports model only needs to carry the small serializable connection/layout config. Replacing config reconnects when ws_url changes and restores changed layouts; theme accepts light, dark, or a Perspective theme name.

Installing this project registers the perspective entry point with spaday. The equivalent explicit forms are packages=[spaday_perspective.package] and packages=["spaday_perspective:package"].

Run the local example

python -m pip install -e ".[examples]"
python -m spaday_perspective.example

Open http://127.0.0.1:8015 to inspect the complete market-monitor example: live native Perspective streaming, flat and grouped layouts, server-authoritative order submission, reactive metrics, and light/dark themes. It passes the local package descriptor directly, so it does not install or resolve the integration from GitHub.

[!NOTE] This library was generated using copier from the Base Python Project Template repository.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spaday_perspective-0.1.1.tar.gz (2.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spaday_perspective-0.1.1-py3-none-any.whl (2.0 MB view details)

Uploaded Python 3

File details

Details for the file spaday_perspective-0.1.1.tar.gz.

File metadata

  • Download URL: spaday_perspective-0.1.1.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for spaday_perspective-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0ffa0c9720eb169398b92ca81449c6d1cb988822f484fd5280143121a1f84f2a
MD5 b22dbe64dba454a34710189396b8b24f
BLAKE2b-256 e9784e960d31451f8b1f7545b310984cd76cb676eb8a61beb624ea3779544788

See more details on using hashes here.

File details

Details for the file spaday_perspective-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for spaday_perspective-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 50900ed883c72f247f1c5c830930835fd38ba58d0b72b84f1c45812cce08de15
MD5 598167e630e9b13115e8db65558c0f99
BLAKE2b-256 218e84975891eae733e17010419c14c99fc7d6c93949db064f084344520a9e36

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page