dara-core 1.14.9__py3-none-any.whl → 1.15.0__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/routing.py +2 -1
- dara/core/internal/websocket.py +13 -2
- dara/core/persistence.py +3 -2
- dara/core/umd/dara.core.umd.js +31 -22
- {dara_core-1.14.9.dist-info → dara_core-1.15.0.dist-info}/METADATA +10 -10
- {dara_core-1.14.9.dist-info → dara_core-1.15.0.dist-info}/RECORD +9 -9
- {dara_core-1.14.9.dist-info → dara_core-1.15.0.dist-info}/LICENSE +0 -0
- {dara_core-1.14.9.dist-info → dara_core-1.15.0.dist-info}/WHEEL +0 -0
- {dara_core-1.14.9.dist-info → dara_core-1.15.0.dist-info}/entry_points.txt +0 -0
dara/core/internal/routing.py
CHANGED
|
@@ -490,10 +490,11 @@ def create_router(config: Configuration):
|
|
|
490
490
|
return result
|
|
491
491
|
|
|
492
492
|
@core_api_router.post('/store', dependencies=[Depends(verify_session)])
|
|
493
|
-
async def sync_backend_store(values: Dict[str, Any] = Body()):
|
|
493
|
+
async def sync_backend_store(ws_channel: str = Body(), values: Dict[str, Any] = Body()):
|
|
494
494
|
registry_mgr: RegistryLookup = utils_registry.get('RegistryLookup')
|
|
495
495
|
|
|
496
496
|
async def _write(store_uid: str, value: Any):
|
|
497
|
+
WS_CHANNEL.set(ws_channel)
|
|
497
498
|
store_entry: BackendStoreEntry = await registry_mgr.get(backend_store_registry, store_uid)
|
|
498
499
|
result = store_entry.store.write(value)
|
|
499
500
|
|
dara/core/internal/websocket.py
CHANGED
|
@@ -321,6 +321,9 @@ class WebsocketManager:
|
|
|
321
321
|
|
|
322
322
|
def __init__(self):
|
|
323
323
|
self.handlers: Dict[str, WebSocketHandler] = {}
|
|
324
|
+
"""
|
|
325
|
+
A mapping of channel IDs to WebSocketHandler instances.
|
|
326
|
+
"""
|
|
324
327
|
|
|
325
328
|
def _construct_message(self, payload: LoosePayload, custom: bool) -> ServerMessage:
|
|
326
329
|
"""
|
|
@@ -344,24 +347,30 @@ class WebsocketManager:
|
|
|
344
347
|
self.handlers[channel_id] = handler
|
|
345
348
|
return handler
|
|
346
349
|
|
|
347
|
-
async def broadcast(self, message: LoosePayload, custom=False):
|
|
350
|
+
async def broadcast(self, message: LoosePayload, custom=False, ignore_channel: Optional[str] = None):
|
|
348
351
|
"""
|
|
349
352
|
Send a message to all connected clients.
|
|
350
353
|
|
|
351
354
|
:param message: The message to send
|
|
352
355
|
:param custom: Whether the message is a custom message
|
|
356
|
+
:param ignore_channel: A channel ID to ignore when broadcasting
|
|
353
357
|
"""
|
|
354
358
|
async with anyio.create_task_group() as tg:
|
|
355
359
|
for handler in self.handlers.values():
|
|
360
|
+
if ignore_channel is not None and handler.channel_id == ignore_channel:
|
|
361
|
+
continue
|
|
356
362
|
tg.start_soon(handler.send_message, self._construct_message(message, custom))
|
|
357
363
|
|
|
358
|
-
async def send_message_to_user(
|
|
364
|
+
async def send_message_to_user(
|
|
365
|
+
self, user_id: str, message: LoosePayload, custom=False, ignore_channel: Optional[str] = None
|
|
366
|
+
):
|
|
359
367
|
"""
|
|
360
368
|
Send a message to all connected channels associated with the given user.
|
|
361
369
|
|
|
362
370
|
:param user_id: The user ID to send the message to
|
|
363
371
|
:param message: The message payload to send
|
|
364
372
|
:param custom: Whether the message is a custom message
|
|
373
|
+
:param ignore_channel: A channel ID to ignore when sending
|
|
365
374
|
"""
|
|
366
375
|
channels = get_user_channels(user_id)
|
|
367
376
|
|
|
@@ -370,6 +379,8 @@ class WebsocketManager:
|
|
|
370
379
|
|
|
371
380
|
async with anyio.create_task_group() as tg:
|
|
372
381
|
for channel in channels:
|
|
382
|
+
if ignore_channel is not None and channel == ignore_channel:
|
|
383
|
+
continue
|
|
373
384
|
tg.start_soon(self.send_message, channel, message, custom)
|
|
374
385
|
|
|
375
386
|
async def send_message(self, channel_id: str, message: LoosePayload, custom=False):
|
dara/core/persistence.py
CHANGED
|
@@ -10,6 +10,7 @@ from pydantic import BaseModel, Field, PrivateAttr, validator
|
|
|
10
10
|
|
|
11
11
|
from dara.core.auth.definitions import USER
|
|
12
12
|
from dara.core.internal.utils import run_user_handler
|
|
13
|
+
from dara.core.internal.websocket import WS_CHANNEL
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
15
16
|
from dara.core.interactivity.plain_variable import Variable
|
|
@@ -257,7 +258,7 @@ class BackendStore(PersistenceStore):
|
|
|
257
258
|
msg = {'store_uid': self.uid, 'value': value}
|
|
258
259
|
|
|
259
260
|
if self.scope == 'global':
|
|
260
|
-
return await ws_mgr.broadcast(msg)
|
|
261
|
+
return await ws_mgr.broadcast(msg, ignore_channel=WS_CHANNEL.get())
|
|
261
262
|
|
|
262
263
|
# For user scope, we need to find channels for the user and notify them
|
|
263
264
|
user = USER.get()
|
|
@@ -266,7 +267,7 @@ class BackendStore(PersistenceStore):
|
|
|
266
267
|
return
|
|
267
268
|
|
|
268
269
|
user_identifier = user.identity_id or user.identity_name
|
|
269
|
-
return await ws_mgr.send_message_to_user(user_identifier, msg)
|
|
270
|
+
return await ws_mgr.send_message_to_user(user_identifier, msg, ignore_channel=WS_CHANNEL.get())
|
|
270
271
|
|
|
271
272
|
async def init(self, variable: 'Variable'):
|
|
272
273
|
"""
|
dara/core/umd/dara.core.umd.js
CHANGED
|
@@ -58144,30 +58144,39 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
58144
58144
|
const val = await response.json();
|
|
58145
58145
|
return val;
|
|
58146
58146
|
}, []);
|
|
58147
|
-
const syncStoreValues = React__namespace.useCallback(
|
|
58148
|
-
|
|
58149
|
-
|
|
58150
|
-
const
|
|
58151
|
-
|
|
58152
|
-
extrasMap.
|
|
58147
|
+
const syncStoreValues = React__namespace.useCallback(
|
|
58148
|
+
async ({ diff }) => {
|
|
58149
|
+
const extrasMap = /* @__PURE__ */ new Map();
|
|
58150
|
+
for (const [itemKey, value] of diff.entries()) {
|
|
58151
|
+
const extras = STORE_EXTRAS_MAP.get(itemKey);
|
|
58152
|
+
if (!extrasMap.has(extras)) {
|
|
58153
|
+
extrasMap.set(extras, {});
|
|
58154
|
+
}
|
|
58155
|
+
extrasMap.get(extras)[itemKey] = value;
|
|
58156
|
+
}
|
|
58157
|
+
async function sendRequest(serializableExtras, storeDiff) {
|
|
58158
|
+
const response = await request(
|
|
58159
|
+
`/api/core/store`,
|
|
58160
|
+
{
|
|
58161
|
+
body: JSON.stringify({
|
|
58162
|
+
values: storeDiff,
|
|
58163
|
+
ws_channel: await client.getChannel()
|
|
58164
|
+
}),
|
|
58165
|
+
method: "POST"
|
|
58166
|
+
},
|
|
58167
|
+
serializableExtras.extras
|
|
58168
|
+
);
|
|
58169
|
+
await handleAuthErrors(response, true);
|
|
58170
|
+
await validateResponse(response, `Failed to sync the store values`);
|
|
58153
58171
|
}
|
|
58154
|
-
|
|
58155
|
-
|
|
58156
|
-
|
|
58157
|
-
|
|
58158
|
-
`/api/core/store`,
|
|
58159
|
-
{ body: JSON.stringify(storeDiff), method: "POST" },
|
|
58160
|
-
serializableExtras.extras
|
|
58172
|
+
await Promise.allSettled(
|
|
58173
|
+
Array.from(extrasMap.entries()).map(
|
|
58174
|
+
([serializableExtras, storeDiff]) => sendRequest(serializableExtras, storeDiff)
|
|
58175
|
+
)
|
|
58161
58176
|
);
|
|
58162
|
-
|
|
58163
|
-
|
|
58164
|
-
|
|
58165
|
-
await Promise.allSettled(
|
|
58166
|
-
Array.from(extrasMap.entries()).map(
|
|
58167
|
-
([serializableExtras, storeDiff]) => sendRequest(serializableExtras, storeDiff)
|
|
58168
|
-
)
|
|
58169
|
-
);
|
|
58170
|
-
}, []);
|
|
58177
|
+
},
|
|
58178
|
+
[client]
|
|
58179
|
+
);
|
|
58171
58180
|
const listenToStoreChanges = React__namespace.useCallback(
|
|
58172
58181
|
({ updateItem }) => {
|
|
58173
58182
|
if (!client) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dara-core
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15.0
|
|
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.
|
|
23
|
+
Requires-Dist: create-dara-app (==1.15.0)
|
|
24
24
|
Requires-Dist: croniter (>=1.0.15,<3.0.0)
|
|
25
25
|
Requires-Dist: cryptography (>=42.0.4)
|
|
26
|
-
Requires-Dist: dara-components (==1.
|
|
26
|
+
Requires-Dist: dara-components (==1.15.0) ; 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_dara (==0.3.1.0)
|
|
@@ -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.
|
|
54
|
+
<img src="https://github.com/causalens/dara/blob/v1.15.0/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
|
|
|
@@ -142,9 +142,9 @@ And the supporting UI packages and tools.
|
|
|
142
142
|
- `ui-utils` - miscellaneous utility functions
|
|
143
143
|
- `ui-widgets` - widget components
|
|
144
144
|
|
|
145
|
-
More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.
|
|
145
|
+
More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.15.0/CONTRIBUTING.md) file.
|
|
146
146
|
|
|
147
147
|
## License
|
|
148
148
|
|
|
149
|
-
Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.
|
|
149
|
+
Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.15.0/LICENSE).
|
|
150
150
|
|
|
@@ -54,13 +54,13 @@ dara/core/internal/port_utils.py,sha256=AQOUNiFNBYKVUwQ7i9UlY1NQ3sWb5xh5GkO6P1Bm
|
|
|
54
54
|
dara/core/internal/registries.py,sha256=9WDczIsNeSmzi6aViIq_b14lmmYGGkdsUGHpv0Sg9zo,3278
|
|
55
55
|
dara/core/internal/registry.py,sha256=ONCDusqaL0q59Py_r8-fFVN3vbkkDf5TXzNvbB9SrGQ,4305
|
|
56
56
|
dara/core/internal/registry_lookup.py,sha256=8snHu2wUUsngXjHyHh6eZqL_WwonTTQB6-WBX-R_WZg,2238
|
|
57
|
-
dara/core/internal/routing.py,sha256=
|
|
57
|
+
dara/core/internal/routing.py,sha256=XViBysQSchhX9yoFyDoGe4r5OQ8xMfn6rvA2fi8Yd70,22847
|
|
58
58
|
dara/core/internal/scheduler.py,sha256=z6OYwazBf3GYo8CzMC9IuGC2P96gI7JwxquT8GaoTMk,12944
|
|
59
59
|
dara/core/internal/settings.py,sha256=wAWxl-HXjq7PW3twe_CrR-UuMRw9VBudC3eRmevZAhM,3869
|
|
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=yj_IVDfwyjPmljY-9NWktaM0QGG50KrWQERWrpfNn00,21480
|
|
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
|
|
@@ -80,8 +80,8 @@ dara/core/metrics/__init__.py,sha256=2UqpWHv-Ie58QLJIHJ9Szfjq8xifAuwy5FYGUIFwWtI
|
|
|
80
80
|
dara/core/metrics/cache.py,sha256=ybofUhZO0TCHeyhB_AtldWk1QTmTKh7GucTXpOkeTFA,2580
|
|
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
|
-
dara/core/persistence.py,sha256=
|
|
84
|
-
dara/core/umd/dara.core.umd.js,sha256=
|
|
83
|
+
dara/core/persistence.py,sha256=9GBLhK_so-T-DnNOVT3zo7mHXNjwIU2TzgcIOr7XEro,10497
|
|
84
|
+
dara/core/umd/dara.core.umd.js,sha256=AjBfi7G00OO78EvnWerCpfruED4xAI4PiKgApSQ2HIM,4879029
|
|
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.
|
|
109
|
-
dara_core-1.
|
|
110
|
-
dara_core-1.
|
|
111
|
-
dara_core-1.
|
|
112
|
-
dara_core-1.
|
|
108
|
+
dara_core-1.15.0.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
|
|
109
|
+
dara_core-1.15.0.dist-info/METADATA,sha256=IhMXPa_0o-eECRfArK7m9tXmrGTPYB8k8elFdHI86ME,7390
|
|
110
|
+
dara_core-1.15.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
111
|
+
dara_core-1.15.0.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
|
|
112
|
+
dara_core-1.15.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|