dara-core 1.20.0a1__py3-none-any.whl → 1.20.1a1__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/__init__.py +0 -3
- dara/core/actions.py +2 -1
- dara/core/auth/basic.py +16 -22
- dara/core/auth/definitions.py +2 -2
- dara/core/auth/routes.py +5 -5
- dara/core/auth/utils.py +5 -5
- dara/core/base_definitions.py +64 -22
- dara/core/cli.py +7 -8
- dara/core/configuration.py +2 -5
- dara/core/css.py +2 -1
- dara/core/data_utils.py +19 -18
- dara/core/defaults.py +7 -6
- dara/core/definitions.py +19 -50
- dara/core/http.py +3 -7
- dara/core/interactivity/__init__.py +0 -6
- dara/core/interactivity/actions.py +50 -52
- dara/core/interactivity/any_data_variable.py +134 -7
- dara/core/interactivity/any_variable.py +8 -5
- dara/core/interactivity/data_variable.py +266 -8
- dara/core/interactivity/derived_data_variable.py +290 -7
- dara/core/interactivity/derived_variable.py +174 -414
- dara/core/interactivity/filtering.py +27 -46
- dara/core/interactivity/loop_variable.py +2 -2
- dara/core/interactivity/non_data_variable.py +68 -5
- dara/core/interactivity/plain_variable.py +15 -89
- dara/core/interactivity/switch_variable.py +19 -19
- dara/core/interactivity/url_variable.py +90 -10
- dara/core/internal/cache_store/base_impl.py +1 -2
- dara/core/internal/cache_store/cache_store.py +25 -22
- dara/core/internal/cache_store/keep_all.py +1 -4
- dara/core/internal/cache_store/lru.py +1 -5
- dara/core/internal/cache_store/ttl.py +1 -4
- dara/core/internal/cgroup.py +1 -1
- dara/core/internal/dependency_resolution.py +66 -60
- dara/core/internal/devtools.py +5 -12
- dara/core/internal/download.py +4 -13
- dara/core/internal/encoder_registry.py +7 -7
- dara/core/internal/execute_action.py +13 -13
- dara/core/internal/hashing.py +3 -1
- dara/core/internal/import_discovery.py +4 -3
- dara/core/internal/normalization.py +18 -9
- dara/core/internal/pandas_utils.py +5 -107
- dara/core/internal/pool/definitions.py +1 -1
- dara/core/internal/pool/task_pool.py +16 -25
- dara/core/internal/pool/utils.py +18 -21
- dara/core/internal/pool/worker.py +2 -3
- dara/core/internal/port_utils.py +1 -1
- dara/core/internal/registries.py +6 -12
- dara/core/internal/registry.py +2 -4
- dara/core/internal/registry_lookup.py +5 -11
- dara/core/internal/routing.py +145 -109
- dara/core/internal/scheduler.py +8 -13
- dara/core/internal/settings.py +2 -2
- dara/core/internal/store.py +29 -2
- dara/core/internal/tasks.py +195 -379
- dara/core/internal/utils.py +13 -36
- dara/core/internal/websocket.py +20 -21
- dara/core/js_tooling/js_utils.py +26 -28
- dara/core/js_tooling/templates/vite.config.template.ts +3 -12
- dara/core/logging.py +12 -13
- dara/core/main.py +11 -14
- dara/core/metrics/cache.py +1 -1
- dara/core/metrics/utils.py +3 -3
- dara/core/persistence.py +5 -27
- dara/core/umd/dara.core.umd.js +55425 -59091
- dara/core/visual/components/__init__.py +2 -2
- dara/core/visual/components/fallback.py +4 -30
- dara/core/visual/components/for_cmp.py +1 -4
- dara/core/visual/css/__init__.py +31 -30
- dara/core/visual/dynamic_component.py +28 -31
- dara/core/visual/progress_updater.py +3 -4
- {dara_core-1.20.0a1.dist-info → dara_core-1.20.1a1.dist-info}/METADATA +11 -12
- dara_core-1.20.1a1.dist-info/RECORD +114 -0
- dara/core/interactivity/client_variable.py +0 -71
- dara/core/interactivity/server_variable.py +0 -325
- dara/core/interactivity/state_variable.py +0 -69
- dara/core/interactivity/tabular_variable.py +0 -94
- dara/core/internal/multi_resource_lock.py +0 -70
- dara_core-1.20.0a1.dist-info/RECORD +0 -119
- {dara_core-1.20.0a1.dist-info → dara_core-1.20.1a1.dist-info}/LICENSE +0 -0
- {dara_core-1.20.0a1.dist-info → dara_core-1.20.1a1.dist-info}/WHEEL +0 -0
- {dara_core-1.20.0a1.dist-info → dara_core-1.20.1a1.dist-info}/entry_points.txt +0 -0
dara/core/definitions.py
CHANGED
|
@@ -19,14 +19,15 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import json
|
|
21
21
|
import uuid
|
|
22
|
-
from collections.abc import Awaitable, Mapping
|
|
23
22
|
from enum import Enum
|
|
24
23
|
from typing import (
|
|
25
24
|
Any,
|
|
25
|
+
Awaitable,
|
|
26
26
|
Callable,
|
|
27
27
|
ClassVar,
|
|
28
28
|
List,
|
|
29
29
|
Literal,
|
|
30
|
+
Mapping,
|
|
30
31
|
Optional,
|
|
31
32
|
Protocol,
|
|
32
33
|
Type,
|
|
@@ -84,22 +85,22 @@ class ErrorHandlingConfig(BaseModel):
|
|
|
84
85
|
raw_css: Optional[Any] = None
|
|
85
86
|
"""
|
|
86
87
|
Raw styling to apply to the displayed error boundary.
|
|
87
|
-
Accepts a CSSProperties, dict, str, or
|
|
88
|
+
Accepts a CSSProperties, dict, str, or NonDataVariable.
|
|
88
89
|
"""
|
|
89
90
|
|
|
90
91
|
@field_validator('raw_css', mode='before')
|
|
91
92
|
@classmethod
|
|
92
93
|
def validate_raw_css(cls, value):
|
|
93
|
-
from dara.core.interactivity.
|
|
94
|
+
from dara.core.interactivity.non_data_variable import NonDataVariable
|
|
94
95
|
|
|
95
96
|
if value is None:
|
|
96
97
|
return None
|
|
97
|
-
if isinstance(value, (str,
|
|
98
|
+
if isinstance(value, (str, NonDataVariable, CSSProperties)):
|
|
98
99
|
return value
|
|
99
100
|
if isinstance(value, dict):
|
|
100
101
|
return {_kebab_to_camel(k): v for k, v in value.items()}
|
|
101
102
|
|
|
102
|
-
raise ValueError(f'raw_css must be a CSSProperties, dict, str, None or
|
|
103
|
+
raise ValueError(f'raw_css must be a CSSProperties, dict, str, None or NonDataVariable, got {type(value)}')
|
|
103
104
|
|
|
104
105
|
def model_dump(self, *args, **kwargs):
|
|
105
106
|
result = super().model_dump(*args, **kwargs)
|
|
@@ -145,7 +146,7 @@ class ComponentInstance(BaseModel):
|
|
|
145
146
|
"""
|
|
146
147
|
Raw styling to apply to the component.
|
|
147
148
|
Can be an dict/CSSProperties instance representing the `styles` tag, a string injected directly into the CSS of the wrapping component,
|
|
148
|
-
or a
|
|
149
|
+
or a NonDataVariable resoling to either of the above.
|
|
149
150
|
|
|
150
151
|
```python
|
|
151
152
|
|
|
@@ -174,7 +175,7 @@ class ComponentInstance(BaseModel):
|
|
|
174
175
|
error_handler: Optional[ErrorHandlingConfig] = None
|
|
175
176
|
"""Configure the error handling for the component"""
|
|
176
177
|
|
|
177
|
-
fallback: Optional[
|
|
178
|
+
fallback: Optional[BaseFallback] = None
|
|
178
179
|
"""
|
|
179
180
|
Fallback component to render in place of the actual UI if it has not finished loading
|
|
180
181
|
"""
|
|
@@ -196,27 +197,10 @@ class ComponentInstance(BaseModel):
|
|
|
196
197
|
def __repr__(self):
|
|
197
198
|
return '__dara__' + json.dumps(jsonable_encoder(self))
|
|
198
199
|
|
|
199
|
-
@field_validator('fallback', mode='before')
|
|
200
|
-
@classmethod
|
|
201
|
-
def validate_fallback(cls, fallback):
|
|
202
|
-
if fallback is None:
|
|
203
|
-
return None
|
|
204
|
-
|
|
205
|
-
if isinstance(fallback, BaseFallback):
|
|
206
|
-
return fallback
|
|
207
|
-
|
|
208
|
-
# wrap custom component in fallback.custom
|
|
209
|
-
if isinstance(fallback, ComponentInstance):
|
|
210
|
-
from dara.core.visual.components.fallback import Fallback
|
|
211
|
-
|
|
212
|
-
return Fallback.Custom(component=fallback)
|
|
213
|
-
|
|
214
|
-
raise ValueError(f'fallback must be a BaseFallback or ComponentInstance, got {type(fallback)}')
|
|
215
|
-
|
|
216
200
|
@field_validator('raw_css', mode='before')
|
|
217
201
|
@classmethod
|
|
218
202
|
def parse_css(cls, css: Optional[Any]):
|
|
219
|
-
from dara.core.interactivity.
|
|
203
|
+
from dara.core.interactivity.non_data_variable import NonDataVariable
|
|
220
204
|
|
|
221
205
|
if css is None:
|
|
222
206
|
return None
|
|
@@ -225,10 +209,10 @@ class ComponentInstance(BaseModel):
|
|
|
225
209
|
if isinstance(css, dict):
|
|
226
210
|
return {_kebab_to_camel(k): v for k, v in css.items()}
|
|
227
211
|
|
|
228
|
-
if isinstance(css, (
|
|
212
|
+
if isinstance(css, (NonDataVariable, CSSProperties, str)):
|
|
229
213
|
return css
|
|
230
214
|
|
|
231
|
-
raise ValueError(f'raw_css must be a CSSProperties, dict, str, None or
|
|
215
|
+
raise ValueError(f'raw_css must be a CSSProperties, dict, str, None or NonDataVariable, got {type(css)}')
|
|
232
216
|
|
|
233
217
|
@classmethod
|
|
234
218
|
def isinstance(cls, obj: Any) -> bool:
|
|
@@ -280,7 +264,8 @@ class CallableClassComponent(Protocol):
|
|
|
280
264
|
Callable class component protocol. Describes any class with a __call__ instance method returning a component instance.
|
|
281
265
|
"""
|
|
282
266
|
|
|
283
|
-
def __call__(self) -> ComponentInstance:
|
|
267
|
+
def __call__(self) -> ComponentInstance:
|
|
268
|
+
...
|
|
284
269
|
|
|
285
270
|
|
|
286
271
|
DiscoverTarget = Union[Callable[..., ComponentInstance], ComponentInstance, Type[CallableClassComponent]]
|
|
@@ -294,7 +279,7 @@ def discover(outer_obj: DiscoverT) -> DiscoverT:
|
|
|
294
279
|
Will make sure to statically register all encountered dependencies of marked functional component or component class.
|
|
295
280
|
Should not be necessary in most cases, mainly useful when creating component libraries.
|
|
296
281
|
"""
|
|
297
|
-
outer_obj.__wrapped_by__ = discover
|
|
282
|
+
outer_obj.__wrapped_by__ = discover # type: ignore
|
|
298
283
|
return outer_obj
|
|
299
284
|
|
|
300
285
|
|
|
@@ -434,8 +419,9 @@ class BaseFallback(StyledComponentInstance):
|
|
|
434
419
|
@field_validator('suspend_render')
|
|
435
420
|
@classmethod
|
|
436
421
|
def validate_suspend_render(cls, value):
|
|
437
|
-
if isinstance(value, int)
|
|
438
|
-
|
|
422
|
+
if isinstance(value, int):
|
|
423
|
+
if value < 0:
|
|
424
|
+
raise ValueError('suspend_render must be a positive integer')
|
|
439
425
|
|
|
440
426
|
return value
|
|
441
427
|
|
|
@@ -475,30 +461,13 @@ class PyComponentDef(BaseModel):
|
|
|
475
461
|
func: Optional[Callable[..., Any]] = None
|
|
476
462
|
name: str
|
|
477
463
|
dynamic_kwargs: Optional[Mapping[str, AnyVariable]] = None
|
|
478
|
-
fallback: Optional[
|
|
464
|
+
fallback: Optional[BaseFallback] = None
|
|
479
465
|
polling_interval: Optional[int] = None
|
|
480
466
|
render_component: Callable[..., Awaitable[Any]]
|
|
481
467
|
"""Handler to render the component. Defaults to dara.core.visual.dynamic_component.render_component"""
|
|
482
468
|
|
|
483
469
|
type: Literal[ComponentType.PY] = ComponentType.PY
|
|
484
470
|
|
|
485
|
-
@field_validator('fallback', mode='before')
|
|
486
|
-
@classmethod
|
|
487
|
-
def validate_fallback(cls, fallback):
|
|
488
|
-
if fallback is None:
|
|
489
|
-
return None
|
|
490
|
-
|
|
491
|
-
if isinstance(fallback, BaseFallback):
|
|
492
|
-
return fallback
|
|
493
|
-
|
|
494
|
-
# wrap custom component in fallback.custom
|
|
495
|
-
if isinstance(fallback, ComponentInstance):
|
|
496
|
-
from dara.core.visual.components.fallback import Fallback
|
|
497
|
-
|
|
498
|
-
return Fallback.Custom(component=fallback)
|
|
499
|
-
|
|
500
|
-
raise ValueError(f'fallback must be a BaseFallback or ComponentInstance, got {type(fallback)}')
|
|
501
|
-
|
|
502
471
|
|
|
503
472
|
# Helper type annotation for working with components
|
|
504
473
|
ComponentTypeAnnotation = Union[PyComponentDef, JsComponentDef]
|
|
@@ -536,7 +505,7 @@ class Page(BaseModel):
|
|
|
536
505
|
icon: Optional[str] = None
|
|
537
506
|
content: ComponentInstanceType
|
|
538
507
|
name: str
|
|
539
|
-
sub_pages: Optional[List[Page]] = []
|
|
508
|
+
sub_pages: Optional[List['Page']] = []
|
|
540
509
|
url_safe_name: str
|
|
541
510
|
include_in_menu: Optional[bool] = None
|
|
542
511
|
on_load: Optional[Action] = None
|
dara/core/http.py
CHANGED
|
@@ -18,7 +18,7 @@ limitations under the License.
|
|
|
18
18
|
import inspect
|
|
19
19
|
from collections import OrderedDict
|
|
20
20
|
from functools import wraps
|
|
21
|
-
from typing import Callable, Dict, List, Type
|
|
21
|
+
from typing import Callable, Dict, List, Type
|
|
22
22
|
|
|
23
23
|
from fastapi import Depends
|
|
24
24
|
from fastapi.params import Depends as DependsType
|
|
@@ -54,10 +54,7 @@ def _get_config_instances(annotations: Dict[str, type]) -> Dict[str, EndpointCon
|
|
|
54
54
|
def _method_decorator(method: HttpMethod):
|
|
55
55
|
"""Create a decorator for a given HTTP method"""
|
|
56
56
|
|
|
57
|
-
def _decorator(url: str, dependencies:
|
|
58
|
-
if dependencies is None:
|
|
59
|
-
dependencies = []
|
|
60
|
-
|
|
57
|
+
def _decorator(url: str, dependencies: List[DependsType] = [], authenticated: bool = True):
|
|
61
58
|
def _inner(func: Callable):
|
|
62
59
|
# Make sure we're using a copy of the dependencies list
|
|
63
60
|
final_dependencies = dependencies[:]
|
|
@@ -107,8 +104,7 @@ def _method_decorator(method: HttpMethod):
|
|
|
107
104
|
|
|
108
105
|
new_handler.__annotations__ = new_annotations
|
|
109
106
|
new_handler.__signature__ = inspect.Signature( # type: ignore
|
|
110
|
-
parameters=list(params.values()),
|
|
111
|
-
return_annotation=sig.return_annotation, # type: ignore
|
|
107
|
+
parameters=list(params.values()), return_annotation=sig.return_annotation # type: ignore
|
|
112
108
|
)
|
|
113
109
|
|
|
114
110
|
return ApiRoute(
|
|
@@ -36,15 +36,12 @@ from dara.core.interactivity.actions import (
|
|
|
36
36
|
)
|
|
37
37
|
from dara.core.interactivity.any_data_variable import AnyDataVariable
|
|
38
38
|
from dara.core.interactivity.any_variable import AnyVariable
|
|
39
|
-
from dara.core.interactivity.client_variable import ClientVariable
|
|
40
39
|
from dara.core.interactivity.condition import Condition, Operator
|
|
41
40
|
from dara.core.interactivity.data_variable import DataVariable
|
|
42
41
|
from dara.core.interactivity.derived_data_variable import DerivedDataVariable
|
|
43
42
|
from dara.core.interactivity.derived_variable import DerivedVariable
|
|
44
43
|
from dara.core.interactivity.non_data_variable import NonDataVariable
|
|
45
44
|
from dara.core.interactivity.plain_variable import Variable
|
|
46
|
-
from dara.core.interactivity.server_variable import ServerVariable
|
|
47
|
-
from dara.core.interactivity.state_variable import StateVariable
|
|
48
45
|
from dara.core.interactivity.switch_variable import SwitchVariable
|
|
49
46
|
from dara.core.interactivity.url_variable import UrlVariable
|
|
50
47
|
|
|
@@ -53,11 +50,9 @@ __all__ = [
|
|
|
53
50
|
'ActionCtx',
|
|
54
51
|
'AnyVariable',
|
|
55
52
|
'AnyDataVariable',
|
|
56
|
-
'ClientVariable',
|
|
57
53
|
'DataVariable',
|
|
58
54
|
'NonDataVariable',
|
|
59
55
|
'Variable',
|
|
60
|
-
'StateVariable',
|
|
61
56
|
'SwitchVariable',
|
|
62
57
|
'DerivedVariable',
|
|
63
58
|
'DerivedDataVariable',
|
|
@@ -72,7 +67,6 @@ __all__ = [
|
|
|
72
67
|
'TriggerVariable',
|
|
73
68
|
'UpdateVariable',
|
|
74
69
|
'UpdateVariableImpl',
|
|
75
|
-
'ServerVariable',
|
|
76
70
|
'SideEffect',
|
|
77
71
|
'Condition',
|
|
78
72
|
'Operator',
|
|
@@ -17,17 +17,16 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
import contextlib
|
|
21
20
|
import inspect
|
|
22
21
|
import math
|
|
23
22
|
import uuid
|
|
24
|
-
from collections.abc import Awaitable
|
|
25
23
|
from contextvars import ContextVar
|
|
26
24
|
from enum import Enum
|
|
27
25
|
from functools import partial, update_wrapper
|
|
28
26
|
from typing import (
|
|
29
27
|
TYPE_CHECKING,
|
|
30
28
|
Any,
|
|
29
|
+
Awaitable,
|
|
31
30
|
Callable,
|
|
32
31
|
ClassVar,
|
|
33
32
|
Dict,
|
|
@@ -44,18 +43,17 @@ import anyio
|
|
|
44
43
|
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
|
45
44
|
from pandas import DataFrame
|
|
46
45
|
from pydantic import ConfigDict
|
|
47
|
-
from typing_extensions import
|
|
46
|
+
from typing_extensions import deprecated
|
|
48
47
|
|
|
49
48
|
from dara.core.base_definitions import (
|
|
50
49
|
ActionDef,
|
|
51
50
|
ActionImpl,
|
|
52
51
|
ActionResolverDef,
|
|
53
52
|
AnnotatedAction,
|
|
54
|
-
TaskProgressUpdate,
|
|
55
53
|
)
|
|
56
54
|
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
57
|
-
from dara.core.
|
|
58
|
-
from dara.core.interactivity.
|
|
55
|
+
from dara.core.base_definitions import TaskProgressUpdate
|
|
56
|
+
from dara.core.interactivity.data_variable import DataVariable
|
|
59
57
|
from dara.core.internal.download import generate_download_code
|
|
60
58
|
from dara.core.internal.registry_lookup import RegistryLookup
|
|
61
59
|
from dara.core.internal.utils import run_user_handler
|
|
@@ -65,8 +63,10 @@ if TYPE_CHECKING:
|
|
|
65
63
|
from dara.core.interactivity import (
|
|
66
64
|
AnyVariable,
|
|
67
65
|
DerivedVariable,
|
|
66
|
+
UrlVariable,
|
|
68
67
|
Variable,
|
|
69
68
|
)
|
|
69
|
+
from dara.core.internal.cache_store import CacheStore
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
class ActionInputs(BaseModel):
|
|
@@ -97,7 +97,7 @@ class ComponentActionContext(ActionContext):
|
|
|
97
97
|
ActionContext for actions that only require component value
|
|
98
98
|
"""
|
|
99
99
|
|
|
100
|
-
inputs: ComponentActionInputs
|
|
100
|
+
inputs: ComponentActionInputs # type: ignore
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
class UpdateVariableImpl(ActionImpl):
|
|
@@ -124,7 +124,7 @@ class UpdateVariableImpl(ActionImpl):
|
|
|
124
124
|
|
|
125
125
|
py_name = 'UpdateVariable'
|
|
126
126
|
|
|
127
|
-
variable: Union[Variable,
|
|
127
|
+
variable: Union[Variable, UrlVariable, DataVariable]
|
|
128
128
|
value: Any
|
|
129
129
|
|
|
130
130
|
INPUT: ClassVar[str] = '__dara_input__'
|
|
@@ -134,18 +134,19 @@ class UpdateVariableImpl(ActionImpl):
|
|
|
134
134
|
"""Special value for `value` that will toggle the variable value"""
|
|
135
135
|
|
|
136
136
|
async def execute(self, ctx: ActionCtx) -> Any:
|
|
137
|
-
if isinstance(self.variable,
|
|
137
|
+
if isinstance(self.variable, DataVariable):
|
|
138
138
|
# Update on the backend
|
|
139
139
|
from dara.core.internal.registries import (
|
|
140
|
-
|
|
140
|
+
data_variable_registry,
|
|
141
141
|
utils_registry,
|
|
142
142
|
)
|
|
143
143
|
|
|
144
|
+
store: CacheStore = utils_registry.get('Store')
|
|
144
145
|
registry_mgr: RegistryLookup = utils_registry.get('RegistryLookup')
|
|
145
146
|
|
|
146
|
-
var_entry = await registry_mgr.get(
|
|
147
|
-
|
|
148
|
-
# Don't notify frontend explicitly, all clients will be notified by
|
|
147
|
+
var_entry = await registry_mgr.get(data_variable_registry, self.variable.uid)
|
|
148
|
+
DataVariable.update_value(var_entry, store, self.value)
|
|
149
|
+
# Don't notify frontend explicitly, all clients will be notified by update_value above
|
|
149
150
|
return None
|
|
150
151
|
|
|
151
152
|
# for non-data variables just ping frontend with the new value
|
|
@@ -161,7 +162,7 @@ class UpdateVariableInputs(ActionInputs):
|
|
|
161
162
|
|
|
162
163
|
|
|
163
164
|
class UpdateVariableContext(ActionContext):
|
|
164
|
-
inputs: UpdateVariableInputs
|
|
165
|
+
inputs: UpdateVariableInputs # type: ignore
|
|
165
166
|
|
|
166
167
|
|
|
167
168
|
@deprecated('Use @action or `UpdateVariableImpl` for simple cases')
|
|
@@ -170,7 +171,7 @@ class UpdateVariable(AnnotatedAction):
|
|
|
170
171
|
@deprecated: Passing in resolvers is deprecated, use `ctx.update` in an `@action` or `UpdateVariableImpl` instead.
|
|
171
172
|
`UpdateVariableImpl` will be renamed to `UpdateVariable` in Dara 2.0.
|
|
172
173
|
|
|
173
|
-
The UpdateVariable action can be passed to any `ComponentInstance` prop accepting an action and trigger the update of a Variable or
|
|
174
|
+
The UpdateVariable action can be passed to any `ComponentInstance` prop accepting an action and trigger the update of a Variable, UrlVariable or DataVariable.
|
|
174
175
|
The resolver function takes a Context param which will feed the `inputs`: `old` and `new` as well as any `extras` passed through.
|
|
175
176
|
|
|
176
177
|
Below an example of how a resolver might look:
|
|
@@ -238,13 +239,13 @@ class UpdateVariable(AnnotatedAction):
|
|
|
238
239
|
|
|
239
240
|
Ctx: ClassVar[type[UpdateVariableContext]] = UpdateVariableContext
|
|
240
241
|
|
|
241
|
-
variable: Union[Variable,
|
|
242
|
+
variable: Union[Variable, DataVariable, UrlVariable]
|
|
242
243
|
extras: Optional[List[AnyVariable]]
|
|
243
244
|
|
|
244
245
|
def __init__(
|
|
245
246
|
self,
|
|
246
247
|
resolver: Callable[[UpdateVariableContext], Any],
|
|
247
|
-
variable: Union[Variable,
|
|
248
|
+
variable: Union[Variable, DataVariable, UrlVariable],
|
|
248
249
|
extras: Optional[List[AnyVariable]] = None,
|
|
249
250
|
):
|
|
250
251
|
"""
|
|
@@ -253,8 +254,8 @@ class UpdateVariable(AnnotatedAction):
|
|
|
253
254
|
:param extras: any extra variables to resolve and pass to the resolution function context
|
|
254
255
|
"""
|
|
255
256
|
|
|
256
|
-
async def _update(ctx: action.Ctx, **kwargs):
|
|
257
|
-
ctx = cast(ActionCtx, ctx)
|
|
257
|
+
async def _update(ctx: action.Ctx, **kwargs): # type: ignore
|
|
258
|
+
ctx = cast(ActionCtx, ctx) # type: ignore
|
|
258
259
|
old = kwargs.pop('old')
|
|
259
260
|
extras = [kwargs[f'kwarg_{idx}'] for idx in range(len(kwargs))]
|
|
260
261
|
old_ctx = UpdateVariableContext(inputs=UpdateVariableInputs(old=old, new=ctx.input), extras=extras)
|
|
@@ -270,7 +271,7 @@ class UpdateVariable(AnnotatedAction):
|
|
|
270
271
|
for idx in range(len(extras or []))
|
|
271
272
|
],
|
|
272
273
|
]
|
|
273
|
-
_update.__signature__ = inspect.Signature(params)
|
|
274
|
+
_update.__signature__ = inspect.Signature(params) # type: ignore
|
|
274
275
|
|
|
275
276
|
# Pass in variable and extras as kwargs
|
|
276
277
|
kwargs = {f'kwarg_{idx}': value for idx, value in enumerate(extras or [])}
|
|
@@ -427,11 +428,11 @@ def NavigateTo(
|
|
|
427
428
|
return NavigateToImpl(url=url, new_tab=new_tab)
|
|
428
429
|
|
|
429
430
|
# Otherwise create a new @action with the provided resolver
|
|
430
|
-
async def _navigate(ctx: action.Ctx, **kwargs):
|
|
431
|
-
ctx = cast(ActionCtx, ctx)
|
|
431
|
+
async def _navigate(ctx: action.Ctx, **kwargs): # type: ignore
|
|
432
|
+
ctx = cast(ActionCtx, ctx) # type: ignore
|
|
432
433
|
extras = [kwargs[f'kwarg_{idx}'] for idx in range(len(kwargs))]
|
|
433
434
|
old_ctx = ComponentActionContext(inputs=ComponentActionInputs(value=ctx.input), extras=extras)
|
|
434
|
-
result = await run_user_handler(url, args=(old_ctx,))
|
|
435
|
+
result = await run_user_handler(url, args=(old_ctx,)) # type: ignore
|
|
435
436
|
# Navigate to resulting url
|
|
436
437
|
await ctx.navigate(result, new_tab)
|
|
437
438
|
|
|
@@ -443,14 +444,14 @@ def NavigateTo(
|
|
|
443
444
|
for idx in range(len(extras or []))
|
|
444
445
|
],
|
|
445
446
|
]
|
|
446
|
-
_navigate.__signature__ = inspect.Signature(params)
|
|
447
|
+
_navigate.__signature__ = inspect.Signature(params) # type: ignore
|
|
447
448
|
|
|
448
449
|
# Pass in variable and extras as kwargs
|
|
449
450
|
kwargs = {f'kwarg_{idx}': value for idx, value in enumerate(extras or [])}
|
|
450
451
|
return action(_navigate)(**kwargs)
|
|
451
452
|
|
|
452
453
|
|
|
453
|
-
NavigateTo.Ctx = ComponentActionContext
|
|
454
|
+
NavigateTo.Ctx = ComponentActionContext # type: ignore
|
|
454
455
|
|
|
455
456
|
|
|
456
457
|
def Logout():
|
|
@@ -626,13 +627,13 @@ def DownloadContent(
|
|
|
626
627
|
|
|
627
628
|
```python
|
|
628
629
|
|
|
629
|
-
from dara.core import action, ConfigurationBuilder,
|
|
630
|
+
from dara.core import action, ConfigurationBuilder, DataVariable, DownloadContent
|
|
630
631
|
from dara.components.components import Button, Stack
|
|
631
632
|
|
|
632
633
|
|
|
633
634
|
# generate data, alternatively you could load it from a file
|
|
634
635
|
df = pandas.DataFrame(data={'x': [1, 2, 3], 'y':[4, 5, 6]})
|
|
635
|
-
my_var =
|
|
636
|
+
my_var = DataVariable(df)
|
|
636
637
|
|
|
637
638
|
config = ConfigurationBuilder()
|
|
638
639
|
|
|
@@ -662,8 +663,8 @@ def DownloadContent(
|
|
|
662
663
|
```
|
|
663
664
|
"""
|
|
664
665
|
|
|
665
|
-
async def _download(ctx: action.Ctx, **kwargs):
|
|
666
|
-
ctx = cast(ActionCtx, ctx)
|
|
666
|
+
async def _download(ctx: action.Ctx, **kwargs): # type: ignore
|
|
667
|
+
ctx = cast(ActionCtx, ctx) # type: ignore
|
|
667
668
|
extras = [kwargs[f'kwarg_{idx}'] for idx in range(len(kwargs))]
|
|
668
669
|
old_ctx = ComponentActionContext(inputs=ComponentActionInputs(value=ctx.input), extras=extras)
|
|
669
670
|
result = await run_user_handler(resolver, args=(old_ctx,))
|
|
@@ -677,7 +678,7 @@ def DownloadContent(
|
|
|
677
678
|
for idx in range(len(extras or []))
|
|
678
679
|
],
|
|
679
680
|
]
|
|
680
|
-
_download.__signature__ = inspect.Signature(params)
|
|
681
|
+
_download.__signature__ = inspect.Signature(params) # type: ignore
|
|
681
682
|
|
|
682
683
|
# Pass in extras as kwargs
|
|
683
684
|
kwargs = {f'kwarg_{idx}': value for idx, value in enumerate(extras or [])}
|
|
@@ -685,7 +686,7 @@ def DownloadContent(
|
|
|
685
686
|
return action(_download)(**kwargs)
|
|
686
687
|
|
|
687
688
|
|
|
688
|
-
DownloadContent.Ctx = ComponentActionContext
|
|
689
|
+
DownloadContent.Ctx = ComponentActionContext # type: ignore
|
|
689
690
|
"""@deprecated retained for backwards compatibility, to be removed in 2.0"""
|
|
690
691
|
|
|
691
692
|
DownloadVariableDef = ActionDef(name='DownloadVariable', js_module='@darajs/core', py_module='dara.core')
|
|
@@ -768,8 +769,8 @@ def SideEffect(
|
|
|
768
769
|
```
|
|
769
770
|
"""
|
|
770
771
|
|
|
771
|
-
async def _effect(ctx: action.Ctx, **kwargs):
|
|
772
|
-
ctx = cast(ActionCtx, ctx)
|
|
772
|
+
async def _effect(ctx: action.Ctx, **kwargs): # type: ignore
|
|
773
|
+
ctx = cast(ActionCtx, ctx) # type: ignore
|
|
773
774
|
extras = [kwargs[f'kwarg_{idx}'] for idx in range(len(kwargs))]
|
|
774
775
|
old_ctx = ComponentActionContext(inputs=ComponentActionInputs(value=ctx.input), extras=extras)
|
|
775
776
|
# Simply run the user handler
|
|
@@ -783,7 +784,7 @@ def SideEffect(
|
|
|
783
784
|
for idx in range(len(extras or []))
|
|
784
785
|
],
|
|
785
786
|
]
|
|
786
|
-
_effect.__signature__ = inspect.Signature(params)
|
|
787
|
+
_effect.__signature__ = inspect.Signature(params) # type: ignore
|
|
787
788
|
|
|
788
789
|
# Pass in extras as kwargs
|
|
789
790
|
kwargs = {f'kwarg_{idx}': value for idx, value in enumerate(extras or [])}
|
|
@@ -791,7 +792,7 @@ def SideEffect(
|
|
|
791
792
|
return action(_effect)(**kwargs)
|
|
792
793
|
|
|
793
794
|
|
|
794
|
-
SideEffect.Ctx = ComponentActionContext
|
|
795
|
+
SideEffect.Ctx = ComponentActionContext # type: ignore
|
|
795
796
|
"""@deprecated retained for backwards compatibility, to be removed in 2.0"""
|
|
796
797
|
|
|
797
798
|
VariableT = TypeVar('VariableT')
|
|
@@ -824,12 +825,14 @@ class ActionCtx:
|
|
|
824
825
|
self._on_action = _on_action
|
|
825
826
|
|
|
826
827
|
@overload
|
|
827
|
-
async def update(self, variable:
|
|
828
|
+
async def update(self, variable: DataVariable, value: Optional[DataFrame]):
|
|
829
|
+
...
|
|
828
830
|
|
|
829
831
|
@overload
|
|
830
|
-
async def update(self, variable: Variable[VariableT], value: VariableT):
|
|
832
|
+
async def update(self, variable: Union[Variable[VariableT], UrlVariable[VariableT]], value: VariableT):
|
|
833
|
+
...
|
|
831
834
|
|
|
832
|
-
async def update(self, variable: Union[Variable,
|
|
835
|
+
async def update(self, variable: Union[Variable, UrlVariable, DataVariable], value: Any):
|
|
833
836
|
"""
|
|
834
837
|
Update a given variable to provided value.
|
|
835
838
|
|
|
@@ -1112,12 +1115,12 @@ class ActionCtx:
|
|
|
1112
1115
|
|
|
1113
1116
|
```python
|
|
1114
1117
|
|
|
1115
|
-
from dara.core import action, ConfigurationBuilder,
|
|
1118
|
+
from dara.core import action, ConfigurationBuilder, DataVariable
|
|
1116
1119
|
from dara.components.components import Button, Stack
|
|
1117
1120
|
|
|
1118
1121
|
# generate data, alternatively you could load it from a file
|
|
1119
1122
|
df = pandas.DataFrame(data={'x': [1, 2, 3], 'y':[4, 5, 6]})
|
|
1120
|
-
my_var =
|
|
1123
|
+
my_var = DataVariable(df)
|
|
1121
1124
|
|
|
1122
1125
|
config = ConfigurationBuilder()
|
|
1123
1126
|
|
|
@@ -1243,7 +1246,6 @@ class ActionCtx:
|
|
|
1243
1246
|
task_mgr: TaskManager = utils_registry.get('TaskManager')
|
|
1244
1247
|
|
|
1245
1248
|
task = Task(func=func, args=args, kwargs=kwargs, on_progress=on_progress)
|
|
1246
|
-
task_mgr.register_task(task)
|
|
1247
1249
|
pending_task = await task_mgr.run_task(task)
|
|
1248
1250
|
return await pending_task.value()
|
|
1249
1251
|
|
|
@@ -1328,7 +1330,7 @@ class action:
|
|
|
1328
1330
|
```
|
|
1329
1331
|
"""
|
|
1330
1332
|
|
|
1331
|
-
Ctx:
|
|
1333
|
+
Ctx: ClassVar[type[ActionCtx]] = ActionCtx
|
|
1332
1334
|
|
|
1333
1335
|
def __init__(self, func: Callable[..., Any]):
|
|
1334
1336
|
from dara.core.internal.execute_action import execute_action
|
|
@@ -1387,10 +1389,11 @@ class action:
|
|
|
1387
1389
|
return bound_f
|
|
1388
1390
|
|
|
1389
1391
|
@overload
|
|
1390
|
-
def __call__(self, ctx: ActionCtx, *args: Any, **kwargs: Any) -> Any:
|
|
1392
|
+
def __call__(self, ctx: ActionCtx, *args: Any, **kwargs: Any) -> Any:
|
|
1393
|
+
...
|
|
1391
1394
|
|
|
1392
1395
|
@overload
|
|
1393
|
-
def __call__(self, *args: Any, **kwargs: Any) -> AnnotatedAction:
|
|
1396
|
+
def __call__(self, *args: Any, **kwargs: Any) -> AnnotatedAction: # type: ignore
|
|
1394
1397
|
...
|
|
1395
1398
|
|
|
1396
1399
|
def __call__(self, *args, **kwargs) -> Union[AnnotatedAction, Any]:
|
|
@@ -1441,10 +1444,10 @@ class action:
|
|
|
1441
1444
|
for key, value in all_kwargs.items():
|
|
1442
1445
|
if key in self.func.__annotations__:
|
|
1443
1446
|
valid_value = True
|
|
1444
|
-
|
|
1445
|
-
with contextlib.suppress(Exception):
|
|
1447
|
+
try:
|
|
1446
1448
|
valid_value = isinstance(value, (self.func.__annotations__[key], AnyVariable))
|
|
1447
|
-
|
|
1449
|
+
except Exception:
|
|
1450
|
+
pass # The type is either not set or something tricky to verify, e.g. union
|
|
1448
1451
|
if not valid_value:
|
|
1449
1452
|
raise TypeError(
|
|
1450
1453
|
f'Argument: {key} was passed as a {type(value)}, but it should be '
|
|
@@ -1455,11 +1458,6 @@ class action:
|
|
|
1455
1458
|
dynamic_kwargs: Dict[str, AnyVariable] = {}
|
|
1456
1459
|
static_kwargs: Dict[str, Any] = {}
|
|
1457
1460
|
for key, kwarg in all_kwargs.items():
|
|
1458
|
-
if isinstance(kwarg, StateVariable):
|
|
1459
|
-
raise ValueError(
|
|
1460
|
-
'StateVariable cannot be used as input to actions. '
|
|
1461
|
-
"StateVariables are internal variables for tracking DerivedVariable ephemeral client state shouldn't be used as action payloads."
|
|
1462
|
-
)
|
|
1463
1461
|
if isinstance(kwarg, AnyVariable):
|
|
1464
1462
|
dynamic_kwargs[key] = kwarg
|
|
1465
1463
|
else:
|