h2o-lightwave 1.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- h2o_lightwave/__init__.py +30 -0
- h2o_lightwave/core.py +508 -0
- h2o_lightwave/graphics.py +841 -0
- h2o_lightwave/py.typed +0 -0
- h2o_lightwave/routing.py +249 -0
- h2o_lightwave/server.py +109 -0
- h2o_lightwave/types.py +14098 -0
- h2o_lightwave/ui.py +4978 -0
- h2o_lightwave/ui_ext.py +52 -0
- h2o_lightwave/version.py +1 -0
- h2o_lightwave-1.7.6.dist-info/METADATA +172 -0
- h2o_lightwave-1.7.6.dist-info/RECORD +14 -0
- h2o_lightwave-1.7.6.dist-info/WHEEL +4 -0
- h2o_lightwave-1.7.6.dist-info/licenses/LICENSE +1 -0
h2o_lightwave/ui_ext.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright 2020 H2O.ai, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
from typing import Optional, Union
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _clean(d: dict) -> dict:
|
|
20
|
+
return {k: v for k, v in d.items() if v is not None}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def boxes(*args: str) -> str:
|
|
24
|
+
"""Create a specification for card's `box` attribute. Indicates where and how to position a card for various layouts.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
args: Either the name of the zone to place the card in, or a specification created using the `box()` function.
|
|
28
|
+
Returns:
|
|
29
|
+
A string intended to be used as a card's `box` attribute.
|
|
30
|
+
"""
|
|
31
|
+
return json.dumps(args)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def box(zone: str, order: Optional[int] = None, size: Optional[Union[str, int]] = None, width: Optional[str] = None,
|
|
35
|
+
height: Optional[str] = None) -> str:
|
|
36
|
+
"""Create a specification for card's `box` attribute. Indicates where and how to position a card.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
zone: The name of the zone to place the card in.
|
|
40
|
+
order: An number that determines the position of this card relative to other cards in the same zone. Cards in the same zone are sorted in ascending `order` and then placed left to right (or top to bottom).
|
|
41
|
+
size: A number that indicates the ratio of available width or height occupied by this card. Defaults to 1 if size, width and height are not provided.
|
|
42
|
+
width: The width of this card, e.g. `200px`, `50%`, etc.
|
|
43
|
+
height: The height of this card, e.g. `200px`, `50%`, etc.
|
|
44
|
+
Returns:
|
|
45
|
+
A string intended to be used as a card's `box` attribute.
|
|
46
|
+
"""
|
|
47
|
+
if size is not None:
|
|
48
|
+
if not isinstance(size, (int, str)):
|
|
49
|
+
raise ValueError('size must be str or int')
|
|
50
|
+
if isinstance(size, int):
|
|
51
|
+
size = str(size)
|
|
52
|
+
return json.dumps(_clean(dict(zone=zone, order=order, size=size, width=width, height=height)))
|
h2o_lightwave/version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '1.7.6'
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: h2o_lightwave
|
|
3
|
+
Version: 1.7.6
|
|
4
|
+
Summary: H2O Wave Python driver for integration with arbitrary python web frameworks.
|
|
5
|
+
Project-URL: Homepage, https://wave.h2o.ai/
|
|
6
|
+
Project-URL: Documentation, https://wave.h2o.ai/
|
|
7
|
+
Project-URL: Repository, https://github.com/h2oai/wave
|
|
8
|
+
Project-URL: Changelog, https://github.com/h2oai/wave/releases
|
|
9
|
+
Author-email: Martin Turoci <martin.turoci@h2o.ai>
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: Data Science,Low code,Machine Learning,Realtime,UI
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Topic :: Communications :: Chat
|
|
23
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
26
|
+
Classifier: Topic :: Software Development :: Widget Sets
|
|
27
|
+
Requires-Python: >=3.8
|
|
28
|
+
Provides-Extra: web
|
|
29
|
+
Requires-Dist: h2o-lightwave-web==1.7.6; extra == 'web'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# H2O Lightwave
|
|
33
|
+
|
|
34
|
+
H2O Lightwave is a lightweight, pure-Python version of [H2O Wave](https://wave.h2o.ai/) that can be embedded in popular async web frameworks like FastAPI, Starlette, etc.
|
|
35
|
+
|
|
36
|
+
In other words, H2O Lightwave works without the Wave server.
|
|
37
|
+
|
|
38
|
+
The integration consists of 2 steps:
|
|
39
|
+
|
|
40
|
+
* Add Wave's web assets directory to your framework's static file handler.
|
|
41
|
+
* Add a webSocket handler, and use `wave_serve()` to connect Wave to your web UI.
|
|
42
|
+
|
|
43
|
+
That's it. You can now render UI elements using pure Python. Lightwave aims to be as minimal as possible and only provides:
|
|
44
|
+
|
|
45
|
+
* A simple way to render your UI.
|
|
46
|
+
* A simple way of capturing the user interactions (like button clicks, dropdown values etc.).
|
|
47
|
+
* Minimal state management.
|
|
48
|
+
|
|
49
|
+
Nothing more, nothing less.
|
|
50
|
+
|
|
51
|
+
Example FastAPI integration:
|
|
52
|
+
|
|
53
|
+
```py
|
|
54
|
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
55
|
+
from fastapi.staticfiles import StaticFiles
|
|
56
|
+
from h2o_lightwave import Q, ui, wave_serve
|
|
57
|
+
from h2o_lightwave_web import web_directory
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Lightwave callback function.
|
|
61
|
+
async def serve(q: Q):
|
|
62
|
+
# Paint our UI on the first page visit.
|
|
63
|
+
if not q.client.initialized:
|
|
64
|
+
# Create a local state.
|
|
65
|
+
q.client.count = 0
|
|
66
|
+
# Add a "card" with a text and a button
|
|
67
|
+
q.page['hello'] = ui.form_card(box='1 1 2 2', items=[
|
|
68
|
+
ui.text_xl('Hello world'),
|
|
69
|
+
ui.button(name='counter', label=f'Current count: {q.client.count}'),
|
|
70
|
+
])
|
|
71
|
+
q.client.initialized = True
|
|
72
|
+
|
|
73
|
+
# Handle counter button click.
|
|
74
|
+
if q.args.counter:
|
|
75
|
+
# Increment the counter.
|
|
76
|
+
q.client.count += 1
|
|
77
|
+
# Update the counter button.
|
|
78
|
+
q.page['hello'].items[1].button.label = f'Current count: {q.client.count}'
|
|
79
|
+
|
|
80
|
+
# Send the UI changes to the browser.
|
|
81
|
+
await q.page.save()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Run: uvicorn hello_fastapi:app.
|
|
85
|
+
# FastAPI boilerplate.
|
|
86
|
+
app = FastAPI()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# FastAPI: WebSocket must be registered before index.html handler.
|
|
90
|
+
@app.websocket("/_s/")
|
|
91
|
+
async def ws(ws: WebSocket):
|
|
92
|
+
try:
|
|
93
|
+
await ws.accept()
|
|
94
|
+
await wave_serve(serve, ws.send_text, ws.receive_text)
|
|
95
|
+
await ws.close()
|
|
96
|
+
except WebSocketDisconnect:
|
|
97
|
+
print('Client disconnected')
|
|
98
|
+
|
|
99
|
+
app.mount("/", StaticFiles(directory=web_directory, html=True), name="/")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
We also recommend reading the [blog post](https://medium.com/@unusualcode/h2o-lightwave-building-web-uis-with-fastapi-and-python-88a915383490) and other [integration examples](https://github.com/h2oai/wave/tree/main/py/h2o_lightwave/examples).
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install "h2o-lightwave[web]"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Lightwave requires websockets to function properly. Not all libraries come with them out of the box so you might need to install them additionally. For example, Starlette & FastAPI requires
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install websockets
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
to be able to expose websocket handlers. This might differ from framework to framework.
|
|
117
|
+
|
|
118
|
+
## Widgets
|
|
119
|
+
|
|
120
|
+
All available widgets can be found [here](https://wave.h2o.ai/docs/widgets/overview). We are working on separate docs for Lightwave.
|
|
121
|
+
|
|
122
|
+
## Custom HTML page
|
|
123
|
+
|
|
124
|
+
Lightwave can also be used only for certain parts of your HTML pages, e.g. for charts. In addition to the integration steps above:
|
|
125
|
+
|
|
126
|
+
* Use the `get_web_files` function which HTML links to scripts and styles for you to inject into your existing HTML.
|
|
127
|
+
* Render a `div` with an id `wave-root` (`<div id='wave-root'></div>`) into which you want Lightwave to render.
|
|
128
|
+
* Render a parent container for `wave-root` that has `position: relative` and has some dimensions attached.
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
{# index_template.html #}
|
|
132
|
+
<!DOCTYPE html>
|
|
133
|
+
<html lang="en">
|
|
134
|
+
|
|
135
|
+
<head>
|
|
136
|
+
<meta charset="UTF-8">
|
|
137
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
138
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
139
|
+
<title>Document</title>
|
|
140
|
+
<!-- Scripts and stylesheets required for Wave to work properly. -->
|
|
141
|
+
{{ wave_files }}
|
|
142
|
+
</head>
|
|
143
|
+
<style>
|
|
144
|
+
/* Must have position: relative and some size specified (e.g. height, flexbox, absolute positioning etc.). */
|
|
145
|
+
.wave-container {
|
|
146
|
+
position: relative;
|
|
147
|
+
height: 800px;
|
|
148
|
+
}
|
|
149
|
+
</style>
|
|
150
|
+
|
|
151
|
+
<!-- Websocket URL can be changed if needed. Defaults to "/_s/". -->
|
|
152
|
+
<body data-wave-socket-url="/custom_socket/">
|
|
153
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
154
|
+
<div class="wave-container">
|
|
155
|
+
<!-- Wave renders here. -->
|
|
156
|
+
<div id="wave-root"></div>
|
|
157
|
+
</div>
|
|
158
|
+
</body>
|
|
159
|
+
|
|
160
|
+
</html>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Configuration
|
|
164
|
+
|
|
165
|
+
By default, Lightwave tries to connect to websocket route at `/_s/`. This can be configured by adding a `data-wave-socket-url` attribute on the HTML body element (`<body data-wave-socket-url='/my_socket_url/'>`).
|
|
166
|
+
|
|
167
|
+
## Links
|
|
168
|
+
|
|
169
|
+
* Website: [https://wave.h2o.ai/](https://wave.h2o.ai/)
|
|
170
|
+
* Releases: [https://pypi.org/project/h2o-wave/](https://pypi.org/project/h2o-wave/)
|
|
171
|
+
* Code: [https://github.com/h2oai/wave](https://github.com/h2oai/wave)
|
|
172
|
+
* Issue tracker: [https://github.com/h2oai/wave/issues](https://github.com/h2oai/wave/issues)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
h2o_lightwave/__init__.py,sha256=gpUT42FqXoR6BwgKHq4Q_yXH_NGtpuN4J9MTjXIVO8s,1140
|
|
2
|
+
h2o_lightwave/core.py,sha256=8jKxQTFC6uAME06XmYcSMwpWaUE7LdAiRnG_i81BN9k,15363
|
|
3
|
+
h2o_lightwave/graphics.py,sha256=HLYrX-lwsMKbyLmy2ClG5L46DA2_hSCEPTsv0gPVoyg,25866
|
|
4
|
+
h2o_lightwave/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
h2o_lightwave/routing.py,sha256=de8GVfUAb6bwFXtsWj6NXmjMVGELknlZb03F-R4ManY,10592
|
|
6
|
+
h2o_lightwave/server.py,sha256=5O55D6LHbX7Xw9mfMhe6ZxHH-fJpOetc5WKQJtDtySU,3850
|
|
7
|
+
h2o_lightwave/types.py,sha256=oEmWG7pl0EyXCSIQQRLOebPTe6oI_nm2HkjGi6Ry5OM,660213
|
|
8
|
+
h2o_lightwave/ui.py,sha256=d9woXqoqJLARvgTsrL1hJ5-iLlwW6HmR7NWriSzK2CA,172443
|
|
9
|
+
h2o_lightwave/ui_ext.py,sha256=zx_2Ec2-p_ztm8brfVaVF0fTQWVDrb_YxcGfVb-wA10,2325
|
|
10
|
+
h2o_lightwave/version.py,sha256=vMMj4nitlrBKFmTUAadBb7pmN17PH90b7xP_hpzRg9U,22
|
|
11
|
+
h2o_lightwave-1.7.6.dist-info/METADATA,sha256=9kByskOuXW54b19vOIenRfk8qQu4KZDsPZZYSt2dfXM,6323
|
|
12
|
+
h2o_lightwave-1.7.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
+
h2o_lightwave-1.7.6.dist-info/licenses/LICENSE,sha256=hpuFayniDwysSKD0tHGELH2KJDVyhUrKS29torRIpqY,53
|
|
14
|
+
h2o_lightwave-1.7.6.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Copyright (c) 2020 H2O.ai, Inc - All Rights Reserved
|