dara-core 1.20.0__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.
Files changed (82) hide show
  1. dara/core/__init__.py +0 -3
  2. dara/core/actions.py +2 -1
  3. dara/core/auth/basic.py +16 -22
  4. dara/core/auth/definitions.py +2 -2
  5. dara/core/auth/routes.py +5 -5
  6. dara/core/auth/utils.py +5 -5
  7. dara/core/base_definitions.py +64 -22
  8. dara/core/cli.py +7 -8
  9. dara/core/configuration.py +2 -5
  10. dara/core/css.py +2 -1
  11. dara/core/data_utils.py +19 -18
  12. dara/core/defaults.py +7 -6
  13. dara/core/definitions.py +19 -50
  14. dara/core/http.py +3 -7
  15. dara/core/interactivity/__init__.py +0 -6
  16. dara/core/interactivity/actions.py +50 -52
  17. dara/core/interactivity/any_data_variable.py +134 -7
  18. dara/core/interactivity/any_variable.py +8 -5
  19. dara/core/interactivity/data_variable.py +266 -8
  20. dara/core/interactivity/derived_data_variable.py +290 -7
  21. dara/core/interactivity/derived_variable.py +176 -416
  22. dara/core/interactivity/filtering.py +27 -46
  23. dara/core/interactivity/loop_variable.py +2 -2
  24. dara/core/interactivity/non_data_variable.py +68 -5
  25. dara/core/interactivity/plain_variable.py +15 -89
  26. dara/core/interactivity/switch_variable.py +19 -19
  27. dara/core/interactivity/url_variable.py +90 -10
  28. dara/core/internal/cache_store/base_impl.py +1 -2
  29. dara/core/internal/cache_store/cache_store.py +25 -22
  30. dara/core/internal/cache_store/keep_all.py +1 -4
  31. dara/core/internal/cache_store/lru.py +1 -5
  32. dara/core/internal/cache_store/ttl.py +1 -4
  33. dara/core/internal/cgroup.py +1 -1
  34. dara/core/internal/dependency_resolution.py +66 -60
  35. dara/core/internal/devtools.py +5 -12
  36. dara/core/internal/download.py +4 -13
  37. dara/core/internal/encoder_registry.py +7 -7
  38. dara/core/internal/execute_action.py +13 -13
  39. dara/core/internal/hashing.py +3 -1
  40. dara/core/internal/import_discovery.py +4 -3
  41. dara/core/internal/normalization.py +18 -9
  42. dara/core/internal/pandas_utils.py +5 -107
  43. dara/core/internal/pool/definitions.py +1 -1
  44. dara/core/internal/pool/task_pool.py +16 -25
  45. dara/core/internal/pool/utils.py +18 -21
  46. dara/core/internal/pool/worker.py +2 -3
  47. dara/core/internal/port_utils.py +1 -1
  48. dara/core/internal/registries.py +6 -12
  49. dara/core/internal/registry.py +2 -4
  50. dara/core/internal/registry_lookup.py +5 -11
  51. dara/core/internal/routing.py +145 -109
  52. dara/core/internal/scheduler.py +8 -13
  53. dara/core/internal/settings.py +2 -2
  54. dara/core/internal/store.py +29 -2
  55. dara/core/internal/tasks.py +195 -379
  56. dara/core/internal/utils.py +13 -36
  57. dara/core/internal/websocket.py +20 -21
  58. dara/core/js_tooling/js_utils.py +26 -28
  59. dara/core/js_tooling/templates/vite.config.template.ts +3 -12
  60. dara/core/logging.py +12 -13
  61. dara/core/main.py +11 -14
  62. dara/core/metrics/cache.py +1 -1
  63. dara/core/metrics/utils.py +3 -3
  64. dara/core/persistence.py +5 -27
  65. dara/core/umd/dara.core.umd.js +55428 -59098
  66. dara/core/visual/components/__init__.py +2 -2
  67. dara/core/visual/components/fallback.py +4 -30
  68. dara/core/visual/components/for_cmp.py +1 -4
  69. dara/core/visual/css/__init__.py +31 -30
  70. dara/core/visual/dynamic_component.py +28 -31
  71. dara/core/visual/progress_updater.py +3 -4
  72. {dara_core-1.20.0.dist-info → dara_core-1.20.1a1.dist-info}/METADATA +11 -12
  73. dara_core-1.20.1a1.dist-info/RECORD +114 -0
  74. dara/core/interactivity/client_variable.py +0 -71
  75. dara/core/interactivity/server_variable.py +0 -325
  76. dara/core/interactivity/state_variable.py +0 -69
  77. dara/core/interactivity/tabular_variable.py +0 -94
  78. dara/core/internal/multi_resource_lock.py +0 -70
  79. dara_core-1.20.0.dist-info/RECORD +0 -119
  80. {dara_core-1.20.0.dist-info → dara_core-1.20.1a1.dist-info}/LICENSE +0 -0
  81. {dara_core-1.20.0.dist-info → dara_core-1.20.1a1.dist-info}/WHEEL +0 -0
  82. {dara_core-1.20.0.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 ClientVariable.
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.client_variable import ClientVariable
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, ClientVariable, CSSProperties)):
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 ClientVariable, got {type(value)}')
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 ClientVariable resoling to either of the above.
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[Union[BaseFallback, ComponentInstance]] = None
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.client_variable import ClientVariable
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, (ClientVariable, CSSProperties, str)):
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 ClientVariable, got {type(css)}')
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 # type: ignore
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) and value < 0:
438
- raise ValueError('suspend_render must be a positive integer')
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[Union[BaseFallback, ComponentInstance]] = None
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, Union
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: Union[List[DependsType], None] = None, authenticated: bool = True):
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 TypeAlias, deprecated
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.interactivity.server_variable import ServerVariable
58
- from dara.core.interactivity.state_variable import StateVariable
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 # type: ignore
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, ServerVariable]
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, ServerVariable):
137
+ if isinstance(self.variable, DataVariable):
138
138
  # Update on the backend
139
139
  from dara.core.internal.registries import (
140
- server_variable_registry,
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(server_variable_registry, self.variable.uid)
147
- await ServerVariable.write_value(var_entry, self.value)
148
- # Don't notify frontend explicitly, all clients will be notified by write_value above
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 # type: ignore
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 ServerVariable.
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, ServerVariable]
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, ServerVariable],
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): # type: ignore
257
- ctx = cast(ActionCtx, ctx) # type: ignore
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) # type: ignore
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): # type: ignore
431
- ctx = cast(ActionCtx, ctx) # type: ignore
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,)) # type: ignore
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) # type: ignore
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 # type: ignore
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, ServerVariable, DownloadContent
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 = ServerVariable(df)
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): # type: ignore
666
- ctx = cast(ActionCtx, ctx) # type: ignore
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) # type: ignore
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 # type: ignore
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): # type: ignore
772
- ctx = cast(ActionCtx, ctx) # type: ignore
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) # type: ignore
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 # type: ignore
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: ServerVariable, value: Optional[DataFrame]): ...
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, ServerVariable], value: Any):
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, ServerVariable
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 = ServerVariable(df)
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: TypeAlias = ActionCtx
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: # type: ignore
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
- # The type is either not set or something tricky to verify, e.g. union
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: