dara-core 1.12.4__py3-none-any.whl → 1.12.5__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.
- dara/core/internal/websocket.py +62 -12
- dara/core/umd/dara.core.umd.js +40 -2
- {dara_core-1.12.4.dist-info → dara_core-1.12.5.dist-info}/METADATA +10 -10
- {dara_core-1.12.4.dist-info → dara_core-1.12.5.dist-info}/RECORD +7 -7
- {dara_core-1.12.4.dist-info → dara_core-1.12.5.dist-info}/LICENSE +0 -0
- {dara_core-1.12.4.dist-info → dara_core-1.12.5.dist-info}/WHEEL +0 -0
- {dara_core-1.12.4.dist-info → dara_core-1.12.5.dist-info}/entry_points.txt +0 -0
dara/core/internal/websocket.py
CHANGED
|
@@ -14,7 +14,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
-
|
|
17
|
+
import asyncio
|
|
18
|
+
import inspect
|
|
18
19
|
import math
|
|
19
20
|
import uuid
|
|
20
21
|
from contextvars import ContextVar
|
|
@@ -51,9 +52,22 @@ class DaraClientMessage(BaseModel):
|
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
class CustomClientMessagePayload(BaseModel):
|
|
55
|
+
rchan: Optional[str] = Field(default=None, alias='__rchan')
|
|
56
|
+
"""Return channel if the message is expected to have a response for"""
|
|
57
|
+
|
|
54
58
|
kind: str
|
|
55
59
|
data: Any
|
|
56
60
|
|
|
61
|
+
def dict(self, *args, **kwargs):
|
|
62
|
+
# Force by_alias to True to use __rchan name
|
|
63
|
+
result = super().dict(*args, **{**kwargs, 'by_alias': True})
|
|
64
|
+
|
|
65
|
+
# remove rchan if None
|
|
66
|
+
if '__rchan' in result and result.get('__rchan') is None:
|
|
67
|
+
result.pop('__rchan')
|
|
68
|
+
|
|
69
|
+
return result
|
|
70
|
+
|
|
57
71
|
|
|
58
72
|
class CustomClientMessage(BaseModel):
|
|
59
73
|
"""
|
|
@@ -71,6 +85,9 @@ class ServerMessagePayload(BaseModel):
|
|
|
71
85
|
rchan: Optional[str] = Field(default=None, alias='__rchan')
|
|
72
86
|
"""Return channel if the message is expected to have a response for"""
|
|
73
87
|
|
|
88
|
+
response_for: Optional[str] = Field(default=None, alias='__response_for')
|
|
89
|
+
"""ID of the __rchan included in the original client message if this message is a response to a client message"""
|
|
90
|
+
|
|
74
91
|
class Config:
|
|
75
92
|
extra = 'allow'
|
|
76
93
|
|
|
@@ -82,6 +99,10 @@ class ServerMessagePayload(BaseModel):
|
|
|
82
99
|
if '__rchan' in result and result.get('__rchan') is None:
|
|
83
100
|
result.pop('__rchan')
|
|
84
101
|
|
|
102
|
+
# remove response_for if None
|
|
103
|
+
if '__response_for' in result and result.get('__response_for') is None:
|
|
104
|
+
result.pop('__response_for')
|
|
105
|
+
|
|
85
106
|
return result
|
|
86
107
|
|
|
87
108
|
|
|
@@ -159,11 +180,13 @@ class WebSocketHandler:
|
|
|
159
180
|
"""
|
|
160
181
|
await self.send_stream.send(message)
|
|
161
182
|
|
|
162
|
-
|
|
183
|
+
def process_client_message(self, message: ClientMessage):
|
|
163
184
|
"""
|
|
164
185
|
Process a message received from the client.
|
|
165
186
|
Handles resolving pending responses.
|
|
166
187
|
|
|
188
|
+
Can return a coroutine to be awaited by the caller.
|
|
189
|
+
|
|
167
190
|
:param message: The message to process
|
|
168
191
|
"""
|
|
169
192
|
if message.type == 'message':
|
|
@@ -190,26 +213,51 @@ class WebSocketHandler:
|
|
|
190
213
|
self.pending_responses[message_id] = (event, message.message)
|
|
191
214
|
event.set()
|
|
192
215
|
|
|
216
|
+
return None
|
|
217
|
+
|
|
193
218
|
if message.type == 'custom':
|
|
194
219
|
# import required internals
|
|
195
220
|
from dara.core.internal.registries import custom_ws_handlers_registry
|
|
196
|
-
from dara.core.internal.utils import run_user_handler
|
|
197
221
|
|
|
198
222
|
data = message.message.data
|
|
199
223
|
kind = message.message.kind
|
|
200
224
|
|
|
201
225
|
try:
|
|
202
226
|
handler = custom_ws_handlers_registry.get(kind)
|
|
203
|
-
response = await run_user_handler(handler, args=(self.channel_id, data))
|
|
204
227
|
|
|
205
|
-
#
|
|
206
|
-
if
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
228
|
+
# Sync handler are processed directly, async ones scheduled as a task
|
|
229
|
+
if inspect.iscoroutinefunction(handler):
|
|
230
|
+
|
|
231
|
+
async def wrapper():
|
|
232
|
+
response = await handler(self.channel_id, data)
|
|
233
|
+
if response is not None:
|
|
234
|
+
await self.send_message(
|
|
235
|
+
CustomServerMessage(
|
|
236
|
+
message=CustomServerMessagePayload(
|
|
237
|
+
kind=kind, data=response, __response_for=message.message.rchan
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
asyncio.create_task(wrapper())
|
|
243
|
+
return None
|
|
244
|
+
else:
|
|
245
|
+
response = handler(self.channel_id, data)
|
|
246
|
+
if response is not None:
|
|
247
|
+
# Return a coroutine for the caller to await
|
|
248
|
+
return self.send_message(
|
|
249
|
+
CustomServerMessage(
|
|
250
|
+
message=CustomServerMessagePayload(
|
|
251
|
+
kind=kind, data=response, __response_for=message.message.rchan
|
|
252
|
+
)
|
|
253
|
+
)
|
|
254
|
+
)
|
|
210
255
|
except KeyError as e:
|
|
211
256
|
eng_logger.error(f'No handler found for custom message kind {kind}', e)
|
|
212
|
-
|
|
257
|
+
return None
|
|
258
|
+
|
|
259
|
+
# unreachable but needed for pylint to be happy
|
|
260
|
+
return None
|
|
213
261
|
|
|
214
262
|
async def send_and_wait(self, message: ServerMessage) -> Optional[Any]:
|
|
215
263
|
"""
|
|
@@ -446,8 +494,10 @@ async def ws_handler(websocket: WebSocket, token: Optional[str] = Query(default=
|
|
|
446
494
|
else:
|
|
447
495
|
try:
|
|
448
496
|
parsed_data = parse_obj_as(ClientMessage, data)
|
|
449
|
-
|
|
450
|
-
|
|
497
|
+
result = handler.process_client_message(parsed_data)
|
|
498
|
+
# Process the resulting coroutine before moving on to next message
|
|
499
|
+
if inspect.iscoroutine(result):
|
|
500
|
+
await result
|
|
451
501
|
except Exception as e:
|
|
452
502
|
eng_logger.error('Error processing client WS message', error=e)
|
|
453
503
|
|
dara/core/umd/dara.core.umd.js
CHANGED
|
@@ -26409,6 +26409,19 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
26409
26409
|
}
|
|
26410
26410
|
}).call(commonjsGlobal$1);
|
|
26411
26411
|
})(lodash$2, lodash$2.exports);
|
|
26412
|
+
let nanoid = (size2 = 21) => crypto.getRandomValues(new Uint8Array(size2)).reduce((id, byte) => {
|
|
26413
|
+
byte &= 63;
|
|
26414
|
+
if (byte < 36) {
|
|
26415
|
+
id += byte.toString(36);
|
|
26416
|
+
} else if (byte < 62) {
|
|
26417
|
+
id += (byte - 26).toString(36).toUpperCase();
|
|
26418
|
+
} else if (byte > 62) {
|
|
26419
|
+
id += "-";
|
|
26420
|
+
} else {
|
|
26421
|
+
id += "_";
|
|
26422
|
+
}
|
|
26423
|
+
return id;
|
|
26424
|
+
}, "");
|
|
26412
26425
|
styled__default.default.span`
|
|
26413
26426
|
display: flex;
|
|
26414
26427
|
flex-direction: column;
|
|
@@ -29610,7 +29623,8 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
29610
29623
|
CodeComponentThemes2["LIGHT"] = "light";
|
|
29611
29624
|
})(CodeComponentThemes || (CodeComponentThemes = {}));
|
|
29612
29625
|
styled__default.default.pre`
|
|
29613
|
-
|
|
29626
|
+
overflow-x: auto;
|
|
29627
|
+
|
|
29614
29628
|
margin: 0;
|
|
29615
29629
|
padding: 1rem;
|
|
29616
29630
|
|
|
@@ -56561,8 +56575,31 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
56561
56575
|
);
|
|
56562
56576
|
}
|
|
56563
56577
|
}
|
|
56564
|
-
sendCustomMessage(kind, data) {
|
|
56578
|
+
sendCustomMessage(kind, data, awaitResponse = false) {
|
|
56565
56579
|
if (this.socket.readyState === WebSocket.OPEN) {
|
|
56580
|
+
if (awaitResponse) {
|
|
56581
|
+
const rchan = nanoid();
|
|
56582
|
+
return new Promise((resolve) => {
|
|
56583
|
+
const subscription = this.customMessages$().pipe().subscribe({
|
|
56584
|
+
next: (msg) => {
|
|
56585
|
+
if (msg.message.__response_for === rchan) {
|
|
56586
|
+
resolve(msg);
|
|
56587
|
+
subscription.unsubscribe();
|
|
56588
|
+
}
|
|
56589
|
+
}
|
|
56590
|
+
});
|
|
56591
|
+
this.socket.send(
|
|
56592
|
+
JSON.stringify({
|
|
56593
|
+
message: {
|
|
56594
|
+
data,
|
|
56595
|
+
kind,
|
|
56596
|
+
__rchan: rchan
|
|
56597
|
+
},
|
|
56598
|
+
type: "custom"
|
|
56599
|
+
})
|
|
56600
|
+
);
|
|
56601
|
+
});
|
|
56602
|
+
}
|
|
56566
56603
|
this.socket.send(
|
|
56567
56604
|
JSON.stringify({
|
|
56568
56605
|
message: {
|
|
@@ -56572,6 +56609,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
56572
56609
|
type: "custom"
|
|
56573
56610
|
})
|
|
56574
56611
|
);
|
|
56612
|
+
return Promise.resolve(null);
|
|
56575
56613
|
}
|
|
56576
56614
|
}
|
|
56577
56615
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dara-core
|
|
3
|
-
Version: 1.12.
|
|
3
|
+
Version: 1.12.5
|
|
4
4
|
Summary: Dara Framework Core
|
|
5
5
|
Home-page: https://dara.causalens.com/
|
|
6
6
|
License: Apache-2.0
|
|
@@ -20,10 +20,10 @@ Requires-Dist: async-asgi-testclient (>=1.4.11,<2.0.0)
|
|
|
20
20
|
Requires-Dist: certifi (>=2024.7.4)
|
|
21
21
|
Requires-Dist: click (==8.1.3)
|
|
22
22
|
Requires-Dist: colorama (>=0.4.6,<0.5.0)
|
|
23
|
-
Requires-Dist: create-dara-app (==1.12.
|
|
23
|
+
Requires-Dist: create-dara-app (==1.12.5)
|
|
24
24
|
Requires-Dist: croniter (>=1.0.15,<2.0.0)
|
|
25
25
|
Requires-Dist: cryptography (>=42.0.4)
|
|
26
|
-
Requires-Dist: dara-components (==1.12.
|
|
26
|
+
Requires-Dist: dara-components (==1.12.5) ; extra == "all"
|
|
27
27
|
Requires-Dist: exceptiongroup (>=1.1.3,<2.0.0)
|
|
28
28
|
Requires-Dist: fastapi (==0.109.0)
|
|
29
29
|
Requires-Dist: fastapi-vite (==0.3.1)
|
|
@@ -51,7 +51,7 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
|
|
52
52
|
# Dara Application Framework
|
|
53
53
|
|
|
54
|
-
<img src="https://github.com/causalens/dara/blob/v1.12.
|
|
54
|
+
<img src="https://github.com/causalens/dara/blob/v1.12.5/img/dara_light.svg?raw=true">
|
|
55
55
|
|
|
56
56
|

|
|
57
57
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
@@ -96,7 +96,7 @@ source .venv/bin/activate
|
|
|
96
96
|
dara start
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-

|
|
100
100
|
|
|
101
101
|
Note: `pip` installation uses [PEP 660](https://peps.python.org/pep-0660/) `pyproject.toml`-based editable installs which require `pip >= 21.3` and `setuptools >= 64.0.0`. You can upgrade both with:
|
|
102
102
|
|
|
@@ -113,9 +113,9 @@ Explore some of our favorite apps - a great way of getting started and getting t
|
|
|
113
113
|
|
|
114
114
|
| Dara App | Description |
|
|
115
115
|
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
-
|  | Demonstrates how to use incorporate a LLM chat box into your decision app to understand model insights |
|
|
117
|
+
|  | Demonstrates how to enable the user to interact with plots, trigger actions based on clicks, mouse movements and other interactions with `Bokeh` or `Plotly` plots |
|
|
118
|
+
|  | Demonstrates how to use the `CausalGraphViewer` component to display your graphs or networks, customising the displayed information through colors and tooltips, and updating the page based on user interaction. |
|
|
119
119
|
|
|
120
120
|
Check out our [App Gallery](https://dara.causalens.com/gallery) for more inspiration!
|
|
121
121
|
|
|
@@ -127,9 +127,9 @@ This repository covers the Dara Application Framework first-party packages.
|
|
|
127
127
|
- `dara-components`: Components for the Dara Framework.
|
|
128
128
|
- `create-dara-app`: A CLI tool for creating new Dara applications.
|
|
129
129
|
|
|
130
|
-
More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.12.
|
|
130
|
+
More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.12.5/CONTRIBUTING.md) file.
|
|
131
131
|
|
|
132
132
|
## License
|
|
133
133
|
|
|
134
|
-
Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.12.
|
|
134
|
+
Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.12.5/LICENSE).
|
|
135
135
|
|
|
@@ -60,7 +60,7 @@ dara/core/internal/settings.py,sha256=wAWxl-HXjq7PW3twe_CrR-UuMRw9VBudC3eRmevZAh
|
|
|
60
60
|
dara/core/internal/store.py,sha256=qVyU7JfC3zE2vYC2mfjmvECWMlFS9b-nMF1k-alg4Y8,7756
|
|
61
61
|
dara/core/internal/tasks.py,sha256=XK-GTIyge8RBYAfzNs3rmLYVNSKIarCzPdqRSVGg-4M,24728
|
|
62
62
|
dara/core/internal/utils.py,sha256=b1YYkn8qHl6-GY6cCm2MS1NXRS9j_rElYCKMZOxJgrY,8232
|
|
63
|
-
dara/core/internal/websocket.py,sha256=
|
|
63
|
+
dara/core/internal/websocket.py,sha256=dhvE7KnolBHwPy9E6Ac1tjzOn0fAtdhDdcMUs47WuuQ,20138
|
|
64
64
|
dara/core/jinja/index.html,sha256=iykqiRh3H_HkcjHJeeSRXRu45nZ2y1sZX5FLdPRhlQY,726
|
|
65
65
|
dara/core/jinja/index_autojs.html,sha256=MRF5J0vNfzZQm9kPEeLl23sbr08fVSRd_PAUD6Fkc_0,1253
|
|
66
66
|
dara/core/js_tooling/custom_js_scaffold/index.tsx,sha256=FEzSV5o5Nyzxw6eXvGLi7BkEBkXf3brV34_7ATLnY7o,68
|
|
@@ -81,7 +81,7 @@ dara/core/metrics/cache.py,sha256=ybofUhZO0TCHeyhB_AtldWk1QTmTKh7GucTXpOkeTFA,25
|
|
|
81
81
|
dara/core/metrics/runtime.py,sha256=YP-6Dz0GeI9_Yr7bUk_-OqShyFySGH_AKpDO126l6es,1833
|
|
82
82
|
dara/core/metrics/utils.py,sha256=rYlBinxFc7VehFT5cTNXLk8gC74UEj7ZGq6vLgIDpSg,2247
|
|
83
83
|
dara/core/persistence.py,sha256=TO94rPAN7jxZKVCC5YA4eE7GGDoNlCPe-BkkItV2VUE,10379
|
|
84
|
-
dara/core/umd/dara.core.umd.js,sha256=
|
|
84
|
+
dara/core/umd/dara.core.umd.js,sha256=eAzeW0wT8sdeoYKEmTdPPlD_OsxRP9PHJUTko912TAM,4876798
|
|
85
85
|
dara/core/umd/style.css,sha256=YQtQ4veiSktnyONl0CU1iU1kKfcQhreH4iASi1MP7Ak,4095007
|
|
86
86
|
dara/core/visual/__init__.py,sha256=QN0wbG9HPQ_vXh8BO8DnBXeYLIENVTNtRmYzZf1lx7c,577
|
|
87
87
|
dara/core/visual/components/__init__.py,sha256=O-Em_glGdZNO0LLl2RWmJSrQiXKxliXg_PuhVXGT81I,1811
|
|
@@ -105,8 +105,8 @@ dara/core/visual/themes/__init__.py,sha256=aM4mgoIYo2neBSw5FRzswsht7PUKjLthiHLmF
|
|
|
105
105
|
dara/core/visual/themes/dark.py,sha256=UQGDooOc8ric73eHs9E0ltYP4UCrwqQ3QxqN_fb4PwY,1942
|
|
106
106
|
dara/core/visual/themes/definitions.py,sha256=m3oN0txs65MZepqjj7AKMMxybf2aq5fTjcTwJmHqEbk,2744
|
|
107
107
|
dara/core/visual/themes/light.py,sha256=-Tviq8oEwGbdFULoDOqPuHO0UpAZGsBy8qFi0kAGolQ,1944
|
|
108
|
-
dara_core-1.12.
|
|
109
|
-
dara_core-1.12.
|
|
110
|
-
dara_core-1.12.
|
|
111
|
-
dara_core-1.12.
|
|
112
|
-
dara_core-1.12.
|
|
108
|
+
dara_core-1.12.5.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
|
|
109
|
+
dara_core-1.12.5.dist-info/METADATA,sha256=tVMv9uBzRnUMr8zkJch56lrN0WLyJF5KZqzffynj174,6771
|
|
110
|
+
dara_core-1.12.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
111
|
+
dara_core-1.12.5.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
|
|
112
|
+
dara_core-1.12.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|