dara-core 1.16.19__py3-none-any.whl → 1.16.20a1__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/defaults.py +3 -0
- dara/core/interactivity/actions.py +3 -8
- dara/core/interactivity/loop_variable.py +88 -0
- dara/core/interactivity/non_data_variable.py +35 -0
- dara/core/internal/normalization.py +1 -1
- dara/core/umd/dara.core.umd.js +1275 -782
- dara/core/visual/components/__init__.py +3 -0
- dara/core/visual/components/for_cmp.py +149 -0
- {dara_core-1.16.19.dist-info → dara_core-1.16.20a1.dist-info}/METADATA +10 -10
- {dara_core-1.16.19.dist-info → dara_core-1.16.20a1.dist-info}/RECORD +13 -11
- {dara_core-1.16.19.dist-info → dara_core-1.16.20a1.dist-info}/LICENSE +0 -0
- {dara_core-1.16.19.dist-info → dara_core-1.16.20a1.dist-info}/WHEEL +0 -0
- {dara_core-1.16.19.dist-info → dara_core-1.16.20a1.dist-info}/entry_points.txt +0 -0
dara/core/defaults.py
CHANGED
|
@@ -39,6 +39,8 @@ from dara.core.visual.components import (
|
|
|
39
39
|
DynamicComponent,
|
|
40
40
|
DynamicComponentDef,
|
|
41
41
|
Fallback,
|
|
42
|
+
For,
|
|
43
|
+
ForDef,
|
|
42
44
|
Menu,
|
|
43
45
|
MenuDef,
|
|
44
46
|
ProgressTracker,
|
|
@@ -77,6 +79,7 @@ CORE_COMPONENTS: Dict[str, ComponentTypeAnnotation] = {
|
|
|
77
79
|
TopBarFrame.__name__: TopBarFrameDef,
|
|
78
80
|
Fallback.Default.py_component: DefaultFallbackDef,
|
|
79
81
|
Fallback.Row.py_component: RowFallbackDef,
|
|
82
|
+
For.__name__: ForDef,
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
# These actions are provided by the core JS of this module
|
|
@@ -1114,10 +1114,9 @@ class ActionCtx:
|
|
|
1114
1114
|
|
|
1115
1115
|
```python
|
|
1116
1116
|
|
|
1117
|
-
from dara.core import action, ConfigurationBuilder, DataVariable
|
|
1117
|
+
from dara.core import action, ConfigurationBuilder, DataVariable
|
|
1118
1118
|
from dara.components.components import Button, Stack
|
|
1119
1119
|
|
|
1120
|
-
|
|
1121
1120
|
# generate data, alternatively you could load it from a file
|
|
1122
1121
|
df = pandas.DataFrame(data={'x': [1, 2, 3], 'y':[4, 5, 6]})
|
|
1123
1122
|
my_var = DataVariable(df)
|
|
@@ -1126,18 +1125,14 @@ class ActionCtx:
|
|
|
1126
1125
|
|
|
1127
1126
|
@action
|
|
1128
1127
|
async def download_csv(ctx: action.Ctx, my_var_value: DataFrame) -> str:
|
|
1129
|
-
# The file can be created and saved dynamically here, it should then return a string with a path to it
|
|
1130
|
-
# To get the component value, e.g. a select component would return the selected value
|
|
1131
|
-
component_value = ctx.input
|
|
1132
|
-
|
|
1133
1128
|
# Getting the value of data passed as extras to the action
|
|
1134
1129
|
data = my_var_value
|
|
1135
1130
|
|
|
1136
1131
|
# save the data to csv
|
|
1137
1132
|
data.to_csv('<PATH_TO_CSV.csv>')
|
|
1138
1133
|
|
|
1139
|
-
# Instruct the frontend to download the file
|
|
1140
|
-
await ctx.download_file(path='<PATH_TO_CSV.csv>', cleanup=
|
|
1134
|
+
# Instruct the frontend to download the file and clean up afterwards
|
|
1135
|
+
await ctx.download_file(path='<PATH_TO_CSV.csv>', cleanup=True)
|
|
1141
1136
|
|
|
1142
1137
|
|
|
1143
1138
|
def test_page():
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, SerializerFunctionWrapHandler, model_serializer
|
|
4
|
+
|
|
5
|
+
from .non_data_variable import NonDataVariable
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LoopVariable(NonDataVariable):
|
|
9
|
+
"""
|
|
10
|
+
A LoopVariable is a type of variable that represents an item in a list.
|
|
11
|
+
It should be constructed using a parent Variable's `list_item()` method.
|
|
12
|
+
It should only be used in conjunction with the `For` component.
|
|
13
|
+
|
|
14
|
+
By default, the entire value is used as the item and the index in the list is used as the unique key.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from dara.core import Variable
|
|
18
|
+
from dara.core.visual.components import For
|
|
19
|
+
|
|
20
|
+
my_list = Variable([1, 2, 3])
|
|
21
|
+
|
|
22
|
+
# Renders a list of Text component where each item is the corresponding item in the list
|
|
23
|
+
For(
|
|
24
|
+
items=my_list,
|
|
25
|
+
renderer=Text(text=my_list.list_item)
|
|
26
|
+
)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Most of the time, you'll want to store objects in a list. You should then use the `get` property to access specific
|
|
30
|
+
properties of the object and the `key` on the `For` component to specify the unique key.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from dara.core import Variable
|
|
34
|
+
from dara.core.visual.components import For
|
|
35
|
+
|
|
36
|
+
my_list = Variable([{'id': 1, 'name': 'John', 'age': 30}, {'id': 2, 'name': 'Jane', 'age': 25}])
|
|
37
|
+
|
|
38
|
+
# Renders a list of Text component where each item is the corresponding item in the list
|
|
39
|
+
For(
|
|
40
|
+
items=my_list,
|
|
41
|
+
renderer=Text(text=my_list.list_item.get('name')),
|
|
42
|
+
key_accessor='id'
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Alternatively, you can use index access instead of `get` to access specific properties of the object.
|
|
47
|
+
Both `get` and `[]` are equivalent.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
nested: List[str] = Field(default_factory=list)
|
|
51
|
+
|
|
52
|
+
def __init__(self, uid: Optional[str] = None, nested: Optional[List[str]] = None):
|
|
53
|
+
if nested is None:
|
|
54
|
+
nested = []
|
|
55
|
+
super().__init__(uid=uid, nested=nested)
|
|
56
|
+
|
|
57
|
+
def get(self, key: str):
|
|
58
|
+
"""
|
|
59
|
+
Access a nested property of the current item in the list.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from dara.core import Variable
|
|
63
|
+
|
|
64
|
+
my_list_of_objects = Variable([
|
|
65
|
+
{'id': 1, 'name': 'John', 'data': {'city': 'London', 'country': 'UK'}},
|
|
66
|
+
{'id': 2, 'name': 'Jane', 'data': {'city': 'Paris', 'country': 'France'}},
|
|
67
|
+
])
|
|
68
|
+
|
|
69
|
+
# Represents the item 'name' property
|
|
70
|
+
my_list_of_objects.list_item.get('name')
|
|
71
|
+
|
|
72
|
+
# Represents the item 'data.country' property
|
|
73
|
+
my_list_of_objects.list_item.get('data').get('country')
|
|
74
|
+
```
|
|
75
|
+
"""
|
|
76
|
+
return self.model_copy(update={'nested': [*self.nested, key]}, deep=True)
|
|
77
|
+
|
|
78
|
+
def __getitem__(self, key: str):
|
|
79
|
+
return self.get(key)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def list_item(self):
|
|
83
|
+
raise RuntimeError('LoopVariable does not support list_item')
|
|
84
|
+
|
|
85
|
+
@model_serializer(mode='wrap')
|
|
86
|
+
def ser_model(self, nxt: SerializerFunctionWrapHandler):
|
|
87
|
+
parent_dict = nxt(self)
|
|
88
|
+
return {**parent_dict, '__typename': 'LoopVariable', 'uid': str(parent_dict['uid'])}
|
|
@@ -34,3 +34,38 @@ class NonDataVariable(AnyVariable, abc.ABC):
|
|
|
34
34
|
|
|
35
35
|
def __init__(self, uid: Optional[str] = None, **kwargs) -> None:
|
|
36
36
|
super().__init__(uid=uid, **kwargs)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def list_item(self):
|
|
40
|
+
"""
|
|
41
|
+
Get a LoopVariable that represents the current item in the list.
|
|
42
|
+
Should only be used in conjunction with the `For` component.
|
|
43
|
+
|
|
44
|
+
Note that it is a type of a Variable so it can be used in places where a regular Variable is expected.
|
|
45
|
+
|
|
46
|
+
By default, the entire list item is used as the item.
|
|
47
|
+
|
|
48
|
+
`LoopVariable` supports nested property access using `get` or index access i.e. `[]`.
|
|
49
|
+
You can mix and match those two methods to access nested properties as they are equivalent.
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
my_list = Variable(['foo', 'bar', 'baz'])
|
|
53
|
+
|
|
54
|
+
# Represents the entire item in the list
|
|
55
|
+
my_list.list_item
|
|
56
|
+
|
|
57
|
+
my_list_of_objects = Variable([
|
|
58
|
+
{'id': 1, 'name': 'John', 'data': {'city': 'London', 'country': 'UK'}},
|
|
59
|
+
{'id': 2, 'name': 'Jane', 'data': {'city': 'Paris', 'country': 'France'}},
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
# Represents the item 'name' property
|
|
63
|
+
my_list_of_objects.list_item['name']
|
|
64
|
+
|
|
65
|
+
# Represents the item 'data.country' property
|
|
66
|
+
my_list_of_objects.list_item.get('data')['country']
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
from .loop_variable import LoopVariable
|
|
70
|
+
|
|
71
|
+
return LoopVariable()
|
|
@@ -161,7 +161,7 @@ def normalize(obj: JsonLike, check_root: bool = True) -> Tuple[JsonLike, Mapping
|
|
|
161
161
|
if check_root and _is_referrable(obj):
|
|
162
162
|
identifier = _get_identifier(obj)
|
|
163
163
|
# Don't check root again otherwise we end up in an infinite loop, we know it's referrable
|
|
164
|
-
_normalized, _lookup = normalize(obj, False)
|
|
164
|
+
_normalized, _lookup = normalize(obj, check_root=False)
|
|
165
165
|
lookup[identifier] = _normalized
|
|
166
166
|
lookup.update(_lookup)
|
|
167
167
|
output = Placeholder(__ref=identifier)
|