dara-core 1.11.4__py3-none-any.whl → 1.12.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/interactivity/any_data_variable.py +14 -1
- dara/core/interactivity/data_variable.py +46 -6
- dara/core/interactivity/derived_data_variable.py +10 -1
- dara/core/internal/pandas_utils.py +39 -2
- dara/core/internal/routing.py +26 -0
- dara/core/umd/dara.core.umd.js +36 -8
- {dara_core-1.11.4.dist-info → dara_core-1.12.0.dist-info}/METADATA +10 -10
- {dara_core-1.11.4.dist-info → dara_core-1.12.0.dist-info}/RECORD +11 -11
- {dara_core-1.11.4.dist-info → dara_core-1.12.0.dist-info}/LICENSE +0 -0
- {dara_core-1.11.4.dist-info → dara_core-1.12.0.dist-info}/WHEEL +0 -0
- {dara_core-1.11.4.dist-info → dara_core-1.12.0.dist-info}/entry_points.txt +0 -0
|
@@ -18,7 +18,7 @@ limitations under the License.
|
|
|
18
18
|
import abc
|
|
19
19
|
import io
|
|
20
20
|
import os
|
|
21
|
-
from typing import Any, Awaitable, Callable, Literal, Optional, cast
|
|
21
|
+
from typing import Any, Awaitable, Callable, Literal, Optional, TypedDict, Union, cast
|
|
22
22
|
|
|
23
23
|
import pandas
|
|
24
24
|
from fastapi import UploadFile
|
|
@@ -49,6 +49,16 @@ class AnyDataVariable(AnyVariable, abc.ABC):
|
|
|
49
49
|
return self.copy(update={'filters': filters}, deep=True)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
class FieldType(TypedDict):
|
|
53
|
+
name: Union[str, tuple[str, ...]]
|
|
54
|
+
type: Literal['integer', 'number', 'boolean', 'datetime', 'duration', 'any', 'str']
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DataFrameSchema(TypedDict):
|
|
58
|
+
fields: list[FieldType]
|
|
59
|
+
primaryKey: list[str]
|
|
60
|
+
|
|
61
|
+
|
|
52
62
|
class DataVariableRegistryEntry(CachedRegistryEntry):
|
|
53
63
|
"""
|
|
54
64
|
Registry entry for DataVariable.
|
|
@@ -61,6 +71,9 @@ class DataVariableRegistryEntry(CachedRegistryEntry):
|
|
|
61
71
|
get_total_count: Callable[..., Awaitable[int]]
|
|
62
72
|
"""Handler to get the total number of rows in the data variable. Defaults to DataVariable.get_total_count for type=plain, and DerivedDataVariable.get_total_count for type=derived"""
|
|
63
73
|
|
|
74
|
+
get_schema: Callable[..., Awaitable[DataFrameSchema]]
|
|
75
|
+
"""Handler to get the schema for data variable. Defaults to DataVariable.get_schema for type=plain, and DerivedDataVariable.get_schema for type=derived"""
|
|
76
|
+
|
|
64
77
|
class Config:
|
|
65
78
|
extra = 'forbid'
|
|
66
79
|
arbitrary_types_allowed = True
|
|
@@ -17,15 +17,18 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
import asyncio
|
|
21
|
+
from typing import Optional, Union, cast
|
|
21
22
|
|
|
22
23
|
from anyio.abc import TaskGroup
|
|
23
24
|
from pandas import DataFrame
|
|
25
|
+
from pandas.io.json._table_schema import build_table_schema
|
|
24
26
|
from pydantic import BaseModel
|
|
25
27
|
|
|
26
28
|
from dara.core.base_definitions import BaseCachePolicy, Cache, CacheArgType
|
|
27
29
|
from dara.core.interactivity.any_data_variable import (
|
|
28
30
|
AnyDataVariable,
|
|
31
|
+
DataFrameSchema,
|
|
29
32
|
DataVariableRegistryEntry,
|
|
30
33
|
)
|
|
31
34
|
from dara.core.interactivity.filtering import (
|
|
@@ -36,7 +39,7 @@ from dara.core.interactivity.filtering import (
|
|
|
36
39
|
)
|
|
37
40
|
from dara.core.internal.cache_store import CacheStore
|
|
38
41
|
from dara.core.internal.hashing import hash_object
|
|
39
|
-
from dara.core.internal.pandas_utils import append_index
|
|
42
|
+
from dara.core.internal.pandas_utils import append_index, df_convert_to_internal
|
|
40
43
|
from dara.core.internal.utils import call_async
|
|
41
44
|
from dara.core.internal.websocket import WebsocketManager
|
|
42
45
|
from dara.core.logging import eng_logger
|
|
@@ -101,6 +104,7 @@ class DataVariable(AnyDataVariable):
|
|
|
101
104
|
type='plain',
|
|
102
105
|
get_data=DataVariable.get_value,
|
|
103
106
|
get_total_count=DataVariable.get_total_count,
|
|
107
|
+
get_schema=DataVariable.get_schema,
|
|
104
108
|
)
|
|
105
109
|
data_variable_registry.register(
|
|
106
110
|
str(self.uid),
|
|
@@ -124,6 +128,15 @@ class DataVariable(AnyDataVariable):
|
|
|
124
128
|
"""
|
|
125
129
|
return f'data-{uid}'
|
|
126
130
|
|
|
131
|
+
@staticmethod
|
|
132
|
+
def _get_schema_cache_key(uid: str) -> str:
|
|
133
|
+
"""
|
|
134
|
+
Get a unique cache key for the data variable's schema.
|
|
135
|
+
|
|
136
|
+
:param uid: uid of the DataVariable
|
|
137
|
+
"""
|
|
138
|
+
return f'schema-{uid}'
|
|
139
|
+
|
|
127
140
|
@classmethod
|
|
128
141
|
def _get_count_cache_key(cls, uid: str, filters: Optional[Union[FilterQuery, dict]]) -> str:
|
|
129
142
|
return f'{cls._get_cache_key(uid)}_{hash_object(filters)}'
|
|
@@ -189,7 +202,10 @@ class DataVariable(AnyDataVariable):
|
|
|
189
202
|
)
|
|
190
203
|
|
|
191
204
|
if entry is None:
|
|
192
|
-
await
|
|
205
|
+
await asyncio.gather(
|
|
206
|
+
store.set(var_entry, key=cls._get_count_cache_key(var_entry.uid, filters), value=0, pin=True),
|
|
207
|
+
store.set(var_entry, key=cls._get_schema_cache_key(var_entry.uid), value=None, pin=True),
|
|
208
|
+
)
|
|
193
209
|
return None
|
|
194
210
|
|
|
195
211
|
data = None
|
|
@@ -197,10 +213,21 @@ class DataVariable(AnyDataVariable):
|
|
|
197
213
|
if entry.data is not None:
|
|
198
214
|
filtered_data, count = apply_filters(entry.data, coerce_to_filter_query(filters), pagination)
|
|
199
215
|
data = filtered_data
|
|
200
|
-
# Store count for given filters
|
|
201
|
-
await
|
|
216
|
+
# Store count for given filters and schema
|
|
217
|
+
await asyncio.gather(
|
|
218
|
+
store.set(var_entry, key=cls._get_count_cache_key(var_entry.uid, filters), value=count, pin=True),
|
|
219
|
+
store.set(
|
|
220
|
+
var_entry,
|
|
221
|
+
key=cls._get_schema_cache_key(var_entry.uid),
|
|
222
|
+
value=build_table_schema(df_convert_to_internal(entry.data)),
|
|
223
|
+
pin=True,
|
|
224
|
+
),
|
|
225
|
+
)
|
|
202
226
|
else:
|
|
203
|
-
await
|
|
227
|
+
await asyncio.gather(
|
|
228
|
+
store.set(var_entry, key=cls._get_count_cache_key(var_entry.uid, filters), value=0, pin=True),
|
|
229
|
+
store.set(var_entry, key=cls._get_schema_cache_key(var_entry.uid), value=None, pin=True),
|
|
230
|
+
)
|
|
204
231
|
|
|
205
232
|
# TODO: once path is supported, stream&filter from disk
|
|
206
233
|
if entry.path:
|
|
@@ -232,6 +259,19 @@ class DataVariable(AnyDataVariable):
|
|
|
232
259
|
|
|
233
260
|
return entry
|
|
234
261
|
|
|
262
|
+
@classmethod
|
|
263
|
+
async def get_schema(cls, var_entry: DataVariableRegistryEntry, store: CacheStore):
|
|
264
|
+
"""
|
|
265
|
+
Get the schema of the data variable.
|
|
266
|
+
|
|
267
|
+
:param var_entry: variable entry
|
|
268
|
+
:param store: store
|
|
269
|
+
"""
|
|
270
|
+
cache_key = cls._get_schema_cache_key(var_entry.uid)
|
|
271
|
+
entry = await store.get(var_entry, key=cache_key, unpin=True)
|
|
272
|
+
|
|
273
|
+
return cast(DataFrameSchema, entry)
|
|
274
|
+
|
|
235
275
|
def reset(self):
|
|
236
276
|
raise NotImplementedError('DataVariable cannot be reset')
|
|
237
277
|
|
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from typing import Any, Callable, Coroutine, List, Optional, Union
|
|
20
|
+
from typing import Any, Callable, Coroutine, List, Optional, Union, cast
|
|
21
21
|
from uuid import uuid4
|
|
22
22
|
|
|
23
23
|
from pandas import DataFrame
|
|
@@ -31,6 +31,7 @@ from dara.core.base_definitions import (
|
|
|
31
31
|
)
|
|
32
32
|
from dara.core.interactivity.any_data_variable import (
|
|
33
33
|
AnyDataVariable,
|
|
34
|
+
DataFrameSchema,
|
|
34
35
|
DataVariableRegistryEntry,
|
|
35
36
|
)
|
|
36
37
|
from dara.core.interactivity.any_variable import AnyVariable
|
|
@@ -130,6 +131,7 @@ class DerivedDataVariable(AnyDataVariable, DerivedVariable):
|
|
|
130
131
|
uid=str(self.uid),
|
|
131
132
|
get_data=DerivedDataVariable.get_data,
|
|
132
133
|
get_total_count=DerivedDataVariable.get_total_count,
|
|
134
|
+
get_schema=DerivedDataVariable.get_schema,
|
|
133
135
|
),
|
|
134
136
|
)
|
|
135
137
|
|
|
@@ -291,6 +293,13 @@ class DerivedDataVariable(AnyDataVariable, DerivedVariable):
|
|
|
291
293
|
|
|
292
294
|
return entry
|
|
293
295
|
|
|
296
|
+
@classmethod
|
|
297
|
+
async def get_schema(cls, data_entry: DataVariableRegistryEntry, store: CacheStore, cache_key: str):
|
|
298
|
+
"""
|
|
299
|
+
Get the schema of the derived data variable.
|
|
300
|
+
"""
|
|
301
|
+
return cast(DataFrameSchema, await store.get(data_entry, key=cache_key, unpin=True))
|
|
302
|
+
|
|
294
303
|
@classmethod
|
|
295
304
|
async def resolve_value(
|
|
296
305
|
cls,
|
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from typing import Optional, TypeVar
|
|
19
19
|
|
|
20
|
-
from pandas import DataFrame
|
|
20
|
+
from pandas import DataFrame, MultiIndex
|
|
21
21
|
|
|
22
22
|
INDEX = '__index__'
|
|
23
23
|
|
|
@@ -52,5 +52,42 @@ def remove_index(value: value_type) -> value_type:
|
|
|
52
52
|
return value
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
def df_convert_to_internal(original_df: DataFrame) -> DataFrame:
|
|
56
|
+
"""
|
|
57
|
+
Convert a DataFrame to an internal format, with the following modifications:
|
|
58
|
+
- Flatten hierarchical columns to a single level
|
|
59
|
+
- Append a numeric index suffix to all columns
|
|
60
|
+
- Reset each index and append it as a special column
|
|
61
|
+
"""
|
|
62
|
+
df = original_df.copy()
|
|
63
|
+
|
|
64
|
+
# If the DataFrame is already in the correct format, return it as is
|
|
65
|
+
if any(isinstance(c, str) and c.startswith('__col__') for c in df.columns):
|
|
66
|
+
return df
|
|
67
|
+
|
|
68
|
+
# Handle hierarchical columns: [(A, B), (A, C)] -> ['A_B', 'A_C']
|
|
69
|
+
if isinstance(df.columns, MultiIndex):
|
|
70
|
+
df.columns = ['_'.join(col).strip() if col[0] != INDEX else INDEX for col in df.columns.values]
|
|
71
|
+
|
|
72
|
+
# Append a suffix to all columns
|
|
73
|
+
df.columns = [
|
|
74
|
+
f'__col__{i}__{col}' if not (isinstance(col, str) and col.startswith(INDEX)) else col
|
|
75
|
+
for i, col in enumerate(df.columns)
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
# Handle multi-index
|
|
79
|
+
if isinstance(df.index, MultiIndex):
|
|
80
|
+
df.index.names = [
|
|
81
|
+
f'__index__{i}__{x}' if x is not None else f'__index__{i}__level_{i}' for i, x in enumerate(df.index.names)
|
|
82
|
+
]
|
|
83
|
+
df = df.reset_index(names=df.index.names)
|
|
84
|
+
else:
|
|
85
|
+
# Otherwise, handle single index
|
|
86
|
+
df.index.name = f'__index__0__{df.index.name}' if df.index.name is not None else '__index__0__index'
|
|
87
|
+
df = df.reset_index(names=[df.index.name])
|
|
88
|
+
|
|
89
|
+
return df
|
|
90
|
+
|
|
91
|
+
|
|
55
92
|
def df_to_json(df: DataFrame) -> str:
|
|
56
|
-
return df.to_json(orient='records')
|
|
93
|
+
return df_convert_to_internal(df).to_json(orient='records') or ''
|
dara/core/internal/routing.py
CHANGED
|
@@ -16,6 +16,7 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
import inspect
|
|
19
|
+
import json
|
|
19
20
|
import os
|
|
20
21
|
from functools import wraps
|
|
21
22
|
from importlib.metadata import version
|
|
@@ -33,6 +34,7 @@ from fastapi import (
|
|
|
33
34
|
Response,
|
|
34
35
|
UploadFile,
|
|
35
36
|
)
|
|
37
|
+
from fastapi.encoders import jsonable_encoder
|
|
36
38
|
from fastapi.responses import StreamingResponse
|
|
37
39
|
from pandas import DataFrame
|
|
38
40
|
from pydantic import BaseModel
|
|
@@ -384,6 +386,30 @@ def create_router(config: Configuration):
|
|
|
384
386
|
except ValueError as e:
|
|
385
387
|
raise HTTPException(status_code=400, detail=str(e))
|
|
386
388
|
|
|
389
|
+
class DataVariableSchemaRequestBody(BaseModel):
|
|
390
|
+
cache_key: Optional[str]
|
|
391
|
+
|
|
392
|
+
@core_api_router.get('/data-variable/{uid}/schema', dependencies=[Depends(verify_session)])
|
|
393
|
+
async def get_data_variable_schema(uid: str, body: Optional[DataVariableSchemaRequestBody] = None):
|
|
394
|
+
try:
|
|
395
|
+
store: CacheStore = utils_registry.get('Store')
|
|
396
|
+
registry_mgr: RegistryLookup = utils_registry.get('RegistryLookup')
|
|
397
|
+
variable_def = await registry_mgr.get(data_variable_registry, uid)
|
|
398
|
+
|
|
399
|
+
if variable_def.type == 'plain':
|
|
400
|
+
return await variable_def.get_schema(variable_def, store)
|
|
401
|
+
|
|
402
|
+
if body is None or body.cache_key is None:
|
|
403
|
+
raise HTTPException(
|
|
404
|
+
status_code=400, detail="Cache key is required when requesting DerivedDataVariable's schema"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
data = await variable_def.get_schema(variable_def, store, body.cache_key)
|
|
408
|
+
content = json.dumps(jsonable_encoder(data)) if isinstance(data, dict) else data
|
|
409
|
+
return Response(content=content, media_type='application/json')
|
|
410
|
+
except ValueError as e:
|
|
411
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
412
|
+
|
|
387
413
|
@core_api_router.post('/data/upload', dependencies=[Depends(verify_session)])
|
|
388
414
|
async def upload_data(
|
|
389
415
|
data_uid: Optional[str] = None,
|
dara/core/umd/dara.core.umd.js
CHANGED
|
@@ -33844,6 +33844,8 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
33844
33844
|
styled__default.default.div`
|
|
33845
33845
|
position: relative;
|
|
33846
33846
|
|
|
33847
|
+
display: flex;
|
|
33848
|
+
flex-direction: column;
|
|
33847
33849
|
gap: 0.5rem;
|
|
33848
33850
|
|
|
33849
33851
|
width: 100%;
|
|
@@ -33871,7 +33873,9 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
33871
33873
|
display: flex;
|
|
33872
33874
|
flex-direction: column;
|
|
33873
33875
|
gap: 0.5rem;
|
|
33876
|
+
|
|
33874
33877
|
width: 100%;
|
|
33878
|
+
|
|
33875
33879
|
color: ${(props) => props.theme.colors.text};
|
|
33876
33880
|
overflow-wrap: break-word;
|
|
33877
33881
|
`;
|
|
@@ -33881,6 +33885,7 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
33881
33885
|
color: ${(props) => props.theme.colors.grey4};
|
|
33882
33886
|
`;
|
|
33883
33887
|
styled__default.default(Trash)`
|
|
33888
|
+
cursor: pointer;
|
|
33884
33889
|
height: 0.8rem;
|
|
33885
33890
|
color: ${(props) => props.theme.colors.secondary};
|
|
33886
33891
|
|
|
@@ -33893,6 +33898,7 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
33893
33898
|
}
|
|
33894
33899
|
`;
|
|
33895
33900
|
styled__default.default(PenToSquare)`
|
|
33901
|
+
cursor: pointer;
|
|
33896
33902
|
height: 0.8rem;
|
|
33897
33903
|
color: ${(props) => props.theme.colors.secondary};
|
|
33898
33904
|
|
|
@@ -57513,18 +57519,32 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
57513
57519
|
await validateResponse(response, "Failed to fetch data variable total count");
|
|
57514
57520
|
return response.json();
|
|
57515
57521
|
}
|
|
57522
|
+
async function fetchDataVariableSchema(uid2, extras, cacheKey) {
|
|
57523
|
+
const response = await request(
|
|
57524
|
+
`/api/core/data-variable/${uid2}/schema`,
|
|
57525
|
+
{ body: JSON.stringify({ cache_key: cacheKey }), method: HTTP_METHOD.GET },
|
|
57526
|
+
extras
|
|
57527
|
+
);
|
|
57528
|
+
await handleAuthErrors(response, true);
|
|
57529
|
+
await validateResponse(response, "Failed to fetch data variable schema");
|
|
57530
|
+
return response.json();
|
|
57531
|
+
}
|
|
57516
57532
|
function useFetchDataVariable(variable, serverTriggerCounter) {
|
|
57517
57533
|
const eventBus = useEventBus();
|
|
57518
57534
|
const extras = useRequestExtras();
|
|
57519
57535
|
const dataCallback = React.useCallback(
|
|
57520
|
-
async (filters, pagination) => {
|
|
57536
|
+
async (filters, pagination, withSchema = false) => {
|
|
57521
57537
|
const mergedFilters = combineFilters("AND", [variable.filters, filters]);
|
|
57522
57538
|
const data = await fetchDataVariable(variable.uid, extras, mergedFilters, pagination);
|
|
57523
|
-
const totalCount = await
|
|
57539
|
+
const [totalCount, schema = null] = await Promise.all([
|
|
57540
|
+
fetchDataVariableCount(variable.uid, extras, mergedFilters),
|
|
57541
|
+
...withSchema ? [fetchDataVariableSchema(variable.uid, extras)] : []
|
|
57542
|
+
]);
|
|
57524
57543
|
eventBus.publish("DATA_VARIABLE_LOADED", { variable, value: { data, totalCount } });
|
|
57525
57544
|
return {
|
|
57526
57545
|
data,
|
|
57527
|
-
totalCount
|
|
57546
|
+
totalCount,
|
|
57547
|
+
...schema !== null && { schema }
|
|
57528
57548
|
};
|
|
57529
57549
|
},
|
|
57530
57550
|
[variable, extras, serverTriggerCounter, eventBus]
|
|
@@ -57534,9 +57554,9 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
57534
57554
|
function useFetchDerivedDataVariable(variable, taskContext, wsClient, dvValuePromise) {
|
|
57535
57555
|
const eventBus = useEventBus();
|
|
57536
57556
|
const extras = useRequestExtras();
|
|
57537
|
-
const previousResult = React.useRef({ data: null, totalCount: 0 });
|
|
57557
|
+
const previousResult = React.useRef({ data: null, totalCount: 0, schema: { fields: [], primaryKey: [] } });
|
|
57538
57558
|
const dataCallback = React.useCallback(
|
|
57539
|
-
async (filters, pagination) => {
|
|
57559
|
+
async (filters, pagination, withSchema = false) => {
|
|
57540
57560
|
const mergedFilters = combineFilters("AND", [variable.filters, filters]);
|
|
57541
57561
|
const dvValue = await dvValuePromise;
|
|
57542
57562
|
const response = await fetchDerivedDataVariable(
|
|
@@ -57565,12 +57585,20 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
|
|
|
57565
57585
|
} else {
|
|
57566
57586
|
data = response;
|
|
57567
57587
|
}
|
|
57568
|
-
const totalCount =
|
|
57569
|
-
|
|
57588
|
+
const [totalCount, schema = null] = await Promise.all([
|
|
57589
|
+
fetchDataVariableCount(variable.uid, extras, mergedFilters),
|
|
57590
|
+
...withSchema ? [fetchDataVariableSchema(variable.uid, extras)] : []
|
|
57591
|
+
]);
|
|
57592
|
+
previousResult.current = {
|
|
57593
|
+
data,
|
|
57594
|
+
totalCount,
|
|
57595
|
+
...schema !== null && { schema }
|
|
57596
|
+
};
|
|
57570
57597
|
eventBus.publish("DERIVED_DATA_VARIABLE_LOADED", { variable, value: { data, totalCount } });
|
|
57571
57598
|
return {
|
|
57572
57599
|
data,
|
|
57573
|
-
totalCount
|
|
57600
|
+
totalCount,
|
|
57601
|
+
...schema !== null && { schema }
|
|
57574
57602
|
};
|
|
57575
57603
|
},
|
|
57576
57604
|
[variable, extras, dvValuePromise, eventBus]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dara-core
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.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.12.0)
|
|
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.
|
|
26
|
+
Requires-Dist: dara-components (==1.12.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 (==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.
|
|
54
|
+
<img src="https://github.com/causalens/dara/blob/v1.12.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
|
|
|
@@ -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.
|
|
130
|
+
More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.12.0/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.
|
|
134
|
+
Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.12.0/LICENSE).
|
|
135
135
|
|
|
@@ -16,11 +16,11 @@ dara/core/definitions.py,sha256=S64F4celEbiQphAlP-_B-ScRv4io0zYhrTl8mNPKav0,2114
|
|
|
16
16
|
dara/core/http.py,sha256=LR1Kr5Hca-Z6klNl-M8R8Q1eOfFh3hLrjVS3kVrRsKA,4658
|
|
17
17
|
dara/core/interactivity/__init__.py,sha256=sYMipjx2wgaAkS5sk7HVSEsvFXlbdqAN2W1vRycQzQk,2501
|
|
18
18
|
dara/core/interactivity/actions.py,sha256=uWrlz4U_K5PQECSYYiDNVB9Imc1-K3LqAnWm2Lyn1Lk,45393
|
|
19
|
-
dara/core/interactivity/any_data_variable.py,sha256=
|
|
19
|
+
dara/core/interactivity/any_data_variable.py,sha256=npgtgAIEKNix8VGYLFCc1G3jwXr195G-1lPejj9hCB8,5261
|
|
20
20
|
dara/core/interactivity/any_variable.py,sha256=HuQTcCw1ysqYcJ5T9Jl--nV_1XzDWMfGw26g6eaQM2k,13281
|
|
21
21
|
dara/core/interactivity/condition.py,sha256=ynK53cGuVMC852X6kkbrgltcdpIX7Otw7j1DEXEO4Q8,1424
|
|
22
|
-
dara/core/interactivity/data_variable.py,sha256=
|
|
23
|
-
dara/core/interactivity/derived_data_variable.py,sha256=
|
|
22
|
+
dara/core/interactivity/data_variable.py,sha256=KIN2V2ipESfhczBtmyPnZUi0iirlZXdN1S1P0aPPVRA,11099
|
|
23
|
+
dara/core/interactivity/derived_data_variable.py,sha256=5TqUdKQD4ncv7MTJuRFcyjWuQnF_TCjK85DCwx6eiUM,13860
|
|
24
24
|
dara/core/interactivity/derived_variable.py,sha256=6xOv-E5wQj-fd9S2RVmRdE_DfkvxVGyptfZlDSj0fmY,21497
|
|
25
25
|
dara/core/interactivity/filtering.py,sha256=F80lkbI6_9wfEiV6jRDA7p4RWIFPwFqOQ6bf8JerfaI,8815
|
|
26
26
|
dara/core/interactivity/non_data_variable.py,sha256=ewPaNaTpMixR5YCVY1pjmyHgeC53K0CsjQxMusbJsiw,1147
|
|
@@ -43,7 +43,7 @@ dara/core/internal/execute_action.py,sha256=4lcU4ElyMlaybIv5oDlahsncJA4PM-6hLOKb
|
|
|
43
43
|
dara/core/internal/hashing.py,sha256=vDlChxGrmpVsyxN3Vg3Bu0GFF7_baIRkrz059kZa4Rk,1133
|
|
44
44
|
dara/core/internal/import_discovery.py,sha256=rh9RS-NCkux_dShIe-XXjX2LiJQN8WiJ5cltrb0YlUE,7853
|
|
45
45
|
dara/core/internal/normalization.py,sha256=eLr1X-5fazlVmPgq8j1Qw_dLVwkVwTF9CRtSa6y5pCk,6894
|
|
46
|
-
dara/core/internal/pandas_utils.py,sha256=
|
|
46
|
+
dara/core/internal/pandas_utils.py,sha256=hWOGZbfuakDulviMpaedpi4mhP45hpe9HSRCiDhlF44,2913
|
|
47
47
|
dara/core/internal/pool/__init__.py,sha256=pBbXE5GR3abVC9Lg3i0QxfdmsrBDMJUYAYb0SiAEBkk,657
|
|
48
48
|
dara/core/internal/pool/channel.py,sha256=TbyIE-PnfzzsQYhl3INOs5UIHHbF_h9bMFne5FjbWlQ,4948
|
|
49
49
|
dara/core/internal/pool/definitions.py,sha256=ICw_Krf-ziVGkzKl4qvvIgKC0Z06bvUehELH5-VMjV0,4645
|
|
@@ -54,7 +54,7 @@ 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=bUtb3lJYYM9NdHUtSWhizKkmTfM3STkoD6t1H3igvnc,2063
|
|
57
|
-
dara/core/internal/routing.py,sha256=
|
|
57
|
+
dara/core/internal/routing.py,sha256=balTwv1aq_vLasKFuIs5Vhw14NRg-iLAQUusflmPazg,22665
|
|
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
|
|
@@ -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=r50GaubVbv_sIpixLI6lPHhgrhp97ZvJjZk6A-Pz3vU,4875647
|
|
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.12.0.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
|
|
109
|
+
dara_core-1.12.0.dist-info/METADATA,sha256=VbDHE5HYcMbUU7d_DYMxtshD7VapN1I2RUnxQZ2zYa8,6771
|
|
110
|
+
dara_core-1.12.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
111
|
+
dara_core-1.12.0.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
|
|
112
|
+
dara_core-1.12.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|