Receber por email
← Voltar para o catálogo

PyWry

PyWry is a cross-platform app factory, rendering engine and UI toolkit for Python that produces native desktop, web, and notebook experiences from a single API.

90estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: Apache-2.0

Como adicionar

/plugin marketplace add deeleeramone/PyWry

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/pywry-mpstc26z/svg)](https://www.skillteca.com.br/skills/pywry-mpstc26z)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Jupyter Notebook Skill

This skill covers building PyWry widgets for Jupyter notebooks via MCP tools.

There are two approaches for displaying widgets in Jupyter:

| Approach | Best For | Requires | |----------|----------|----------| | AnyWidget (recommended) | Native Jupyter integration, bidirectional comms | pip install 'pywry[notebook]' | | IFrame (fallback) | When anywidget unavailable | MCP server in headless mode |

Approach 1: AnyWidget (Recommended)

AnyWidget provides native Jupyter widget integration with traitlet-based bidirectional communication. No iframe, no server - just native Jupyter widgets.

Architecture

┌─────────────────────────────────────────────────────────┐
│  Jupyter Notebook                                       │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Cell [1]: # Code from MCP agent                  │  │
│  │            from pywry.widget import PyWryWidget   │  │
│  │            widget = PyWryWidget(                  │  │
│  │                content="<div>...</div>",          │  │
│  │                height="400px"                     │  │
│  │            )                                      │  │
│  │            widget  # Display in cell              │  │
│  ├───────────────────────────────────────────────────┤  │
│  │  Output: ┌─────────────────────────────────────┐  │  │
│  │          │  [Native Jupyter Widget]            │  │  │
│  │          │  Buttons, Charts, Tables, etc.      │  │  │
│  │          └─────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
         ▲
         │ Traitlet sync (bidirectional)
         ▼
┌─────────────────────────────────────────────────────────┐
│  Python Kernel                                          │
│  PyWryWidget instance with .on() event handlers         │
└─────────────────────────────────────────────────────────┘

MCP Workflow for AnyWidget

When asked to create an interactive widget in Jupyter with anywidget installed:

  1. Use build_div to build HTML content
  2. Provide Python code for the user to run

The MCP agent cannot directly instantiate Python objects in the user's kernel. Instead, provide code the user can execute.

Example: Parameter Tuning Widget

When user asks: "Create a widget to tune learning rate and model type"

Step 1: Build the HTML content using MCP tools:

{
  "tool": "build_div",
  "arguments": {
    "component_id": "output",
    "content": "Adjust parameters below",
    "style": "padding: 1rem; min-height: 100px;"
  }
}

Step 2: Provide this Python code to the user:

from pywry.widget import PyWryWidget
from pywry.toolbar import Toolbar, Slider, Select, Option, Button

# Build toolbar
toolbar = Toolbar(position="inside", items=[
    Slider(label="Learning Rate", event="lr", min=0.001, max=0.1, step=0.001, value=0.01),
    Select(label="Model", event="model", options=[
        Option(label="Linear", value="linear"),
        Option(label="Random Forest", value="rf")
    ]),
    Button(label="Train", event="train", variant="primary")
])

# Build HTML with toolbar
html = f'''
<div id="output" style="padding: 1rem; min-height: 100px;">
    Adjust parameters and click Train
</div>
{toolbar.render()}
'''

# Create and display widget
widget = PyWryWidget(content=html, height="350px")

# Handle events
def on_train(data, event_type, label):
    print(f"Training with: {data}")
    widget.emit("pywry:set-content", {"id": "output", "html": "<p>Training...</p>"})

widget.on("train", on_train)
widget  # Display in cell

AnyWidget Classes

| Class | Use Case | |-------|----------| | PyWryWidget | General HTML/toolbar widgets | | PyWryPlotlyWidget | Charts with Plotly.js bundled | | PyWryAgGridWidget | Data tables with AG Grid bundled |

PyWryPlotlyWidget Example

from pywry.widget import PyWryPlotlyWidget

widget = PyWryPlotlyWidget(
    figure={"data": [{"x": [1,2,3], "y": [4,5,6], "type": "scatter"}]},
    height="450px"
)

# Handle plot click events
widget.on("plotly_click", lambda data, *_: print(f"Clicked: {data}"))
widget

PyWryAgGridWidget Example

from pywry.widget import PyWryAgGridWidget
import pandas as pd

df = pd.DataFrame({"A": [1, 2, 3], "B": ["x", "y", "z"]})

widget = PyWryAgGridWidget(
    data=df.to_dict("records"),
    columns=[{"field": "A"}, {"field": "B"}],
    height="400px"
)

# Handle row selection
widget.on("row_selected", lambda data, *_: print(f"Selected: {data}"))
widget

Approach 2: IFrame (Fallback)

When anywidget is not installed, use the MCP server in headless mode to serve widgets via HTTP.

Architecture

┌─────────────────────────────────────────────────────────┐
│  Jupyter Notebook                                       │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Cell [1]: from IPython.display import IFrame     │  │
│  │            IFrame("http://localhost:8765/widget/  │  │
│  │                   abc123", width="100%",          │  │
│  │                   height=400)                     │  │
│  ├───────────────────────────────────────────────────┤  │
│  │  Output: ┌─────────────────────────────────────┐  │  │
│  │          │  [Your Widget Rendered Here]        │  │  │
│  │          │  Buttons, Charts, Tables, etc.      │  │  │
│  │          └─────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
         ▲
         │ HTTP (iframe src)
         ▼
┌─────────────────────────────────────────────────────────┐
│  PyWry Widget Server (localhost:8765)                   │
│  Serves widget HTML at /widget/{widget_id}              │
└─────────────────────────────────────────────────────────┘

MCP Tool Workflow (IFrame Mode)

Step 1: Create the Widget

Use create_widget to build your widget:

{
  "tool": "create_widget",
  "arguments": {
    "title": "Parameter Tuner",
    "html": "<div id='output'>Adjust parameters below</div>",
    "height": 350,
    "toolbars": [{
      "position": "inside",
      "items": [
        {"type": "slider", "label": "Learning Rate", "event": "lr", "min": 0.001, "max": 0.1, "step": 0.001, "value": 0.01},
        {"type": "select", "label": "Model", "event": "model", "options": [
          {"label": "Linear", "value": "linear"},
          {"label": "Random Forest", "value": "rf"}
        ]}
      ]
    }]
  }
}

Step 2: Provide Display Code to User

The create_widget tool returns:

{
  "widget_id": "abc123",
  "path": "/widget/abc123",
  "created": true
}

IMPORTANT: You must give the user Python code to display the widget. Include this in your response:

from IPython.display import IFrame
IFrame("http://localhost:8765/widget/abc123", width="100%", height=350)

Replace abc123 with the actual widget_id and 350 with the height you used.

Step 3: Poll for Events

Use get_events to check for user interactions:

{
  "tool": "get_events",
  "arguments": {
    "widget_id": "abc123",
    "clear": true
  }
}

Events contain the user's selections:

{
  "events": [
    {"event_type": "lr", "data": {"value": 0.05}},
    {"event_type": "model", "data": {"value": "rf"}}
  ]
}

Step 4: Update the Widget

Use set_content to update displayed results:

{
  "tool": "set_content",
  "arguments": {
    "widget_id": "abc123",
    "component_id": "output",
    "html": "<p>Training with LR=0.05, Model=Random Forest...</p>"
  }
}

Example Response (IFrame Mode)

When asked to create a widget in Jupyter without anywidget, your response should look like:

I've created a parameter tuning widget. Run this code in a cell to display it:

from IPython.display import IFrame
IFrame("http://localho
Compartilhar X LinkedIn