|
1 | 1 | <div align="center"> |
2 | 2 |
|
3 | | - |
| 3 | + |
4 | 4 |
|
5 | | -**Blazingly fast rendering library for native desktop windows, Jupyter widgets, and browser tabs.** |
| 5 | +</div> |
6 | 6 |
|
7 | | -Full bidirectional Python ↔ JavaScript communication. Get started in minutes, not hours. |
| 7 | +PyWry is a cross-platform rendering engine and desktop UI toolkit for Python. One API, three output targets: |
8 | 8 |
|
9 | | -[](https://pypi.org/project/pywry/) |
10 | | -[](https://pypi.org/project/pywry/) |
11 | | -[](LICENSE) |
12 | | -[](https://deeleeramone.github.io/PyWry/) |
| 9 | +- **Native window** — OS webview via [PyTauri](https://pypi.org/project/pytauri/). Not Qt, not Electron. |
| 10 | +- **Jupyter widget** — anywidget + FastAPI + WebSocket, works in JupyterLab, VS Code, and Colab. |
| 11 | +- **Browser tab** — FastAPI server with Redis state backend for horizontal scaling. |
13 | 12 |
|
14 | | -</div> |
| 13 | +## Installation |
15 | 14 |
|
16 | | ---- |
17 | | - |
18 | | -PyWry is **not** a web dashboard framework. It is a **rendering engine** that targets three output paths from one unified API: |
19 | | - |
20 | | -| Mode | Where It Runs | Backend | |
21 | | -|------|---------------|---------| |
22 | | -| `NEW_WINDOW` / `SINGLE_WINDOW` / `MULTI_WINDOW` | Native OS window | PyTauri (Tauri/Rust) subprocess using OS webview | |
23 | | -| `NOTEBOOK` | Jupyter / VS Code / Colab | anywidget or IFrame + FastAPI + WebSocket | |
24 | | -| `BROWSER` | System browser tab | FastAPI server + WebSocket + Redis | |
25 | | - |
26 | | -Built on [PyTauri](https://pypi.org/project/pytauri/) (Rust's [Tauri](https://tauri.app/) framework), it uses the OS webview instead of bundling a browser engine — a few MBs versus Electron's 150MB+ overhead. |
27 | | - |
28 | | -<details> |
29 | | -<summary><strong>Features at a Glance</strong></summary> |
30 | | - |
31 | | -| Feature | What It Does | |
32 | | -|---------|--------------| |
33 | | -| **Native Windows** | Lightweight OS webview windows (not Electron) | |
34 | | -| **Jupyter Widgets** | Works in notebooks via anywidget with traitlet sync | |
35 | | -| **Browser Mode** | Deploy to web with FastAPI + WebSocket | |
36 | | -| **Toolbar System** | 18 declarative Pydantic components with 7 layout positions | |
37 | | -| **Two-Way Events** | Python ↔ JavaScript with pre-wired Plotly/AgGrid events | |
38 | | -| **Modals** | Overlay dialogs with toolbar components inside | |
39 | | -| **AgGrid Tables** | Pandas → AgGrid conversion with pre-wired grid events | |
40 | | -| **Plotly Charts** | Plotly rendering with custom modebar buttons and plot events | |
41 | | -| **Toast Notifications** | Built-in alert system with configurable positioning | |
42 | | -| **Theming & CSS** | Light/dark modes, 60+ CSS variables, hot reload | |
43 | | -| **Secrets Handling** | Server-side password storage, never rendered in HTML | |
44 | | -| **Security** | Token auth, CSP headers, production presets | |
45 | | -| **Configuration** | Layered TOML files, env vars, security presets | |
46 | | -| **Hot Reload** | Live CSS injection and JS updates during development | |
47 | | -| **Deploy Mode** | Redis state backend for horizontal scaling | |
48 | | -| **MCP Server** | AI agent integration via Model Context Protocol | |
49 | | - |
50 | | -</details> |
| 15 | +Python 3.10–3.14, virtual environment recommended. |
51 | 16 |
|
52 | | -## Installation |
| 17 | +```bash |
| 18 | +pip install pywry |
| 19 | +``` |
53 | 20 |
|
54 | | -Requires Python 3.10–3.14. Install in a virtual environment. |
| 21 | +| Extra | When to use | |
| 22 | +|-------|-------------| |
| 23 | +| `pip install 'pywry[notebook]'` | Jupyter / anywidget integration | |
| 24 | +| `pip install 'pywry[mcp]'` | MCP server for AI agents | |
| 25 | +| `pip install 'pywry[freeze]'` | PyInstaller hook for standalone executables | |
| 26 | +| `pip install 'pywry[all]'` | Everything above | |
55 | 27 |
|
56 | | -<details> |
57 | | -<summary><strong>Linux Prerequisites</strong></summary> |
| 28 | +**Linux only** — install system webview dependencies first: |
58 | 29 |
|
59 | 30 | ```bash |
60 | | -# Ubuntu/Debian |
61 | 31 | sudo apt-get install libwebkit2gtk-4.1-dev libgtk-3-dev libglib2.0-dev \ |
62 | 32 | libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \ |
63 | 33 | libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 \ |
64 | 34 | libxcb-shape0 libgl1 libegl1 |
65 | 35 | ``` |
66 | 36 |
|
67 | | -</details> |
68 | | - |
69 | | -```bash |
70 | | -pip install pywry |
71 | | -``` |
72 | | - |
73 | | -| Extra | Command | Description | |
74 | | -|-------|---------|-------------| |
75 | | -| **notebook** | `pip install 'pywry[notebook]'` | anywidget for Jupyter integration | |
76 | | -| **mcp** | `pip install 'pywry[mcp]'` | Model Context Protocol server for AI agents | |
77 | | -| **all** | `pip install 'pywry[all]'` | All optional dependencies | |
78 | | - |
79 | | -> See [Installation Guide](https://deeleeramone.github.io/PyWry/getting-started/installation/) for full details. |
80 | | -
|
81 | | ---- |
82 | | - |
83 | 37 | ## Quick Start |
84 | 38 |
|
85 | | -### Hello World |
86 | | - |
87 | 39 | ```python |
88 | 40 | from pywry import PyWry |
89 | 41 |
|
90 | 42 | app = PyWry() |
91 | | - |
92 | 43 | app.show("Hello World!") |
93 | | - |
94 | | -app.block() # block the main thread until the window closes |
| 44 | +app.block() |
95 | 45 | ``` |
96 | 46 |
|
97 | | -### Interactive Toolbar |
| 47 | +### Toolbar + callbacks |
98 | 48 |
|
99 | 49 | ```python |
100 | 50 | from pywry import PyWry, Toolbar, Button |
101 | 51 |
|
102 | 52 | app = PyWry() |
103 | 53 |
|
104 | 54 | def on_click(data, event_type, label): |
105 | | - app.emit("pywry:set-content", {"selector": "h1", "text": "Toolbar Works!"}, label) |
| 55 | + app.emit("pywry:set-content", {"selector": "h1", "text": "Clicked!"}, label) |
106 | 56 |
|
107 | | -toolbar = Toolbar( |
108 | | - position="top", |
109 | | - items=[Button(label="Update Text", event="app:click")] |
110 | | -) |
111 | | - |
112 | | -handle = app.show( |
113 | | - "<h1>Hello, World!</h1>", |
114 | | - toolbars=[toolbar], |
| 57 | +app.show( |
| 58 | + "<h1>Hello</h1>", |
| 59 | + toolbars=[Toolbar(position="top", items=[Button(label="Click me", event="app:click")])], |
115 | 60 | callbacks={"app:click": on_click}, |
116 | 61 | ) |
| 62 | +app.block() |
117 | 63 | ``` |
118 | 64 |
|
119 | | -### DataFrame → AgGrid |
| 65 | +### Pandas DataFrame → AgGrid |
120 | 66 |
|
121 | 67 | ```python |
122 | 68 | from pywry import PyWry |
123 | 69 | import pandas as pd |
124 | 70 |
|
125 | 71 | app = PyWry() |
126 | | - |
127 | 72 | df = pd.DataFrame({"name": ["Alice", "Bob", "Carol"], "age": [30, 25, 35]}) |
128 | 73 |
|
129 | 74 | def on_select(data, event_type, label): |
130 | 75 | names = ", ".join(row["name"] for row in data["rows"]) |
131 | | - app.emit("pywry:alert", {"message": f"Selected: {names}" if names else "None selected"}, label) |
| 76 | + app.emit("pywry:alert", {"message": f"Selected: {names}"}, label) |
132 | 77 |
|
133 | | -handle = app.show_dataframe(df, callbacks={"grid:row-selected": on_select}) |
| 78 | +app.show_dataframe(df, callbacks={"grid:row-selected": on_select}) |
| 79 | +app.block() |
134 | 80 | ``` |
135 | 81 |
|
136 | | -### Plotly Chart |
| 82 | +### Plotly chart |
137 | 83 |
|
138 | 84 | ```python |
139 | | -from pywry import PyWry, Toolbar, Button |
| 85 | +from pywry import PyWry |
140 | 86 | import plotly.express as px |
141 | 87 |
|
142 | 88 | app = PyWry(theme="light") |
143 | | - |
144 | 89 | fig = px.scatter(px.data.iris(), x="sepal_width", y="sepal_length", color="species") |
145 | | - |
146 | | -handle = app.show_plotly( |
147 | | - fig, |
148 | | - toolbars=[Toolbar(position="top", items=[Button(label="Reset Zoom", event="app:reset")])], |
149 | | - callbacks={"app:reset": lambda d, e, l: app.emit("plotly:reset-zoom", {}, l)}, |
150 | | -) |
| 90 | +app.show_plotly(fig) |
| 91 | +app.block() |
151 | 92 | ``` |
152 | 93 |
|
153 | | -> See [Quick Start Guide](https://deeleeramone.github.io/PyWry/getting-started/quickstart/) and [Examples](https://deeleeramone.github.io/PyWry/examples/) for more. |
154 | | -
|
155 | | ---- |
156 | | - |
157 | | -## Components |
158 | | - |
159 | | -PyWry includes 18 declarative toolbar components, all Pydantic models with 7 layout positions (`header`, `footer`, `top`, `bottom`, `left`, `right`, `inside`): |
160 | | - |
161 | | -| Component | Description | |
162 | | -|-----------|-------------| |
163 | | -| **Button** | Clickable button — primary, secondary, neutral, ghost, outline, danger, warning, icon | |
164 | | -| **Select** | Dropdown select with `Option` items | |
165 | | -| **MultiSelect** | Multi-select dropdown with checkboxes | |
166 | | -| **TextInput** | Text input with debounce support | |
167 | | -| **SecretInput** | Secure password input — values stored server-side, never in HTML | |
168 | | -| **TextArea** | Multi-line text area | |
169 | | -| **SearchInput** | Search input with debounce | |
170 | | -| **NumberInput** | Numeric input with min/max/step | |
171 | | -| **DateInput** | Date picker | |
172 | | -| **SliderInput** | Slider with optional value display | |
173 | | -| **RangeInput** | Dual-handle range slider | |
174 | | -| **Toggle** | Boolean toggle switch | |
175 | | -| **Checkbox** | Boolean checkbox | |
176 | | -| **RadioGroup** | Radio button group | |
177 | | -| **TabGroup** | Tab navigation | |
178 | | -| **Div** | Container element for content/HTML | |
179 | | -| **Marquee** | Scrolling ticker — scroll, alternate, slide, static | |
180 | | -| **Modal** | Overlay dialog supporting all toolbar components | |
181 | | - |
182 | | -> See [Components Documentation](https://deeleeramone.github.io/PyWry/components/) for live previews, attributes, and usage examples. |
183 | | -
|
184 | | ---- |
185 | | - |
186 | | -## Documentation |
187 | | - |
188 | | -Full documentation is available at **[deeleeramone.github.io/PyWry](https://deeleeramone.github.io/PyWry/)**. |
189 | | - |
190 | | -| Section | Topics | |
191 | | -|---------|--------| |
192 | | -| [Getting Started](https://deeleeramone.github.io/PyWry/getting-started/) | Installation, Quick Start, Rendering Paths | |
193 | | -| [Concepts](https://deeleeramone.github.io/PyWry/getting-started/) | `app.show()`, HtmlContent, Events, Configuration, State & RBAC, Hot Reload | |
194 | | -| [UI](https://deeleeramone.github.io/PyWry/getting-started/) | Toolbar System, Modals, Toasts & Alerts, Theming & CSS | |
195 | | -| [Integrations](https://deeleeramone.github.io/PyWry/getting-started/) | Plotly Charts, AgGrid Tables | |
196 | | -| [Hosting](https://deeleeramone.github.io/PyWry/getting-started/) | Browser Mode, Deploy Mode | |
197 | | -| [Components](https://deeleeramone.github.io/PyWry/components/) | Live previews for all 18 toolbar components + Modal | |
198 | | -| [API Reference](https://deeleeramone.github.io/PyWry/reference/) | Auto-generated API docs for every class and function | |
199 | | -| [MCP Server](https://deeleeramone.github.io/PyWry/mcp/) | AI agent integration via Model Context Protocol | |
| 94 | +## Features |
200 | 95 |
|
201 | | ---- |
| 96 | +- **18 toolbar components** — `Button`, `Select`, `MultiSelect`, `TextInput`, `SecretInput`, `SliderInput`, `RangeInput`, `Toggle`, `Checkbox`, `RadioGroup`, `TabGroup`, `Marquee`, `Modal`, and more. All Pydantic models, 7 layout positions. |
| 97 | +- **Two-way events** — `app.emit()` and `app.on()` bridge Python and JavaScript in both directions. Pre-wired Plotly and AgGrid events included. |
| 98 | +- **Theming** — light/dark modes, 60+ CSS variables, hot reload during development. |
| 99 | +- **Security** — token auth, CSP headers, `SecuritySettings.strict()` / `.permissive()` / `.localhost()` presets. `SecretInput` stores values server-side, never in HTML. |
| 100 | +- **Standalone executables** — PyInstaller hook ships with `pywry[freeze]`. No `.spec` edits or `--hidden-import` flags required. |
| 101 | +- **MCP server** — 25 tools, 8 skills, 20+ resources for AI agent integration. |
202 | 102 |
|
203 | 103 | ## MCP Server |
204 | 104 |
|
205 | | -PyWry includes a built-in [Model Context Protocol](https://modelcontextprotocol.io/) server for AI agent integration — 25 tools, 8 skills, and 20+ resources. |
206 | | - |
207 | 105 | ```bash |
208 | 106 | pip install 'pywry[mcp]' |
209 | 107 | pywry mcp --transport stdio |
210 | 108 | ``` |
211 | 109 |
|
212 | | -> See [MCP Documentation](https://deeleeramone.github.io/PyWry/mcp/) for setup with Claude Desktop, tool reference, and examples. |
| 110 | +See the [MCP docs](https://deeleeramone.github.io/PyWry/mcp/) for Claude Desktop setup and tool reference. |
| 111 | + |
| 112 | +## Standalone Executables |
| 113 | + |
| 114 | +```bash |
| 115 | +pip install 'pywry[freeze]' |
| 116 | +pyinstaller --windowed --name MyApp my_app.py |
| 117 | +``` |
| 118 | + |
| 119 | +The output in `dist/MyApp/` is fully self-contained. Target machines need no Python installation — only the OS webview (WebView2 on Windows 10 1803+, WKWebView on macOS, libwebkit2gtk on Linux). |
| 120 | + |
| 121 | +## Documentation |
| 122 | + |
| 123 | +**[deeleeramone.github.io/PyWry](https://deeleeramone.github.io/PyWry/)** |
213 | 124 |
|
214 | | ---- |
| 125 | +- [Getting Started](https://deeleeramone.github.io/PyWry/getting-started/) — installation, quick start, rendering paths |
| 126 | +- [Concepts](https://deeleeramone.github.io/PyWry/getting-started/) — events, configuration, state, hot reload, RBAC |
| 127 | +- [Components](https://deeleeramone.github.io/PyWry/components/) — live previews for all toolbar components |
| 128 | +- [API Reference](https://deeleeramone.github.io/PyWry/reference/) — auto-generated docs for every class and function |
| 129 | +- [MCP Server](https://deeleeramone.github.io/PyWry/mcp/) — AI agent integration |
215 | 130 |
|
216 | 131 | ## License |
217 | 132 |
|
218 | | -Apache 2.0 — see [LICENSE](LICENSE) for details. |
| 133 | +Apache 2.0 — see [LICENSE](LICENSE). |
0 commit comments