dara-core 1.21.16__py3-none-any.whl → 1.21.17__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/auth/base.py +5 -5
- dara/core/auth/basic.py +3 -3
- dara/core/auth/definitions.py +13 -14
- dara/core/auth/routes.py +7 -5
- dara/core/auth/utils.py +11 -10
- dara/core/base_definitions.py +30 -36
- dara/core/cli.py +7 -8
- dara/core/configuration.py +51 -58
- dara/core/css.py +2 -2
- dara/core/data_utils.py +12 -17
- dara/core/defaults.py +3 -3
- dara/core/definitions.py +58 -63
- dara/core/http.py +4 -4
- dara/core/interactivity/actions.py +34 -42
- dara/core/interactivity/any_data_variable.py +1 -1
- dara/core/interactivity/any_variable.py +6 -5
- dara/core/interactivity/client_variable.py +1 -2
- dara/core/interactivity/condition.py +2 -2
- dara/core/interactivity/data_variable.py +2 -4
- dara/core/interactivity/derived_data_variable.py +7 -10
- dara/core/interactivity/derived_variable.py +45 -51
- dara/core/interactivity/filtering.py +19 -19
- dara/core/interactivity/loop_variable.py +2 -4
- dara/core/interactivity/non_data_variable.py +1 -1
- dara/core/interactivity/plain_variable.py +21 -18
- dara/core/interactivity/server_variable.py +13 -15
- dara/core/interactivity/state_variable.py +4 -5
- dara/core/interactivity/switch_variable.py +16 -16
- dara/core/interactivity/tabular_variable.py +3 -3
- dara/core/interactivity/url_variable.py +3 -3
- dara/core/internal/cache_store/cache_store.py +6 -6
- dara/core/internal/cache_store/keep_all.py +3 -3
- dara/core/internal/cache_store/lru.py +8 -8
- dara/core/internal/cache_store/ttl.py +4 -4
- dara/core/internal/custom_response.py +3 -3
- dara/core/internal/dependency_resolution.py +6 -10
- dara/core/internal/devtools.py +2 -3
- dara/core/internal/download.py +5 -6
- dara/core/internal/encoder_registry.py +7 -11
- dara/core/internal/execute_action.py +5 -5
- dara/core/internal/hashing.py +1 -2
- dara/core/internal/import_discovery.py +7 -9
- dara/core/internal/normalization.py +12 -15
- dara/core/internal/pandas_utils.py +6 -6
- dara/core/internal/pool/channel.py +3 -4
- dara/core/internal/pool/definitions.py +9 -9
- dara/core/internal/pool/task_pool.py +8 -8
- dara/core/internal/pool/utils.py +4 -3
- dara/core/internal/pool/worker.py +3 -3
- dara/core/internal/registries.py +4 -4
- dara/core/internal/registry.py +3 -3
- dara/core/internal/registry_lookup.py +4 -4
- dara/core/internal/routing.py +23 -22
- dara/core/internal/scheduler.py +8 -8
- dara/core/internal/settings.py +1 -2
- dara/core/internal/store.py +9 -9
- dara/core/internal/tasks.py +30 -30
- dara/core/internal/utils.py +9 -15
- dara/core/internal/websocket.py +18 -18
- dara/core/js_tooling/js_utils.py +19 -19
- dara/core/logging.py +13 -13
- dara/core/main.py +4 -5
- dara/core/metrics/cache.py +2 -4
- dara/core/persistence.py +19 -25
- dara/core/router/compat.py +1 -3
- dara/core/router/components.py +10 -10
- dara/core/router/dependency_graph.py +2 -4
- dara/core/router/router.py +43 -42
- dara/core/visual/components/dynamic_component.py +1 -3
- dara/core/visual/components/fallback.py +3 -3
- dara/core/visual/components/for_cmp.py +5 -5
- dara/core/visual/components/menu.py +1 -3
- dara/core/visual/components/router_content.py +1 -3
- dara/core/visual/components/sidebar_frame.py +8 -10
- dara/core/visual/components/theme_provider.py +3 -3
- dara/core/visual/components/topbar_frame.py +8 -10
- dara/core/visual/css/__init__.py +277 -277
- dara/core/visual/dynamic_component.py +18 -22
- dara/core/visual/progress_updater.py +1 -1
- dara/core/visual/template.py +10 -12
- dara/core/visual/themes/definitions.py +46 -46
- {dara_core-1.21.16.dist-info → dara_core-1.21.17.dist-info}/METADATA +12 -13
- dara_core-1.21.17.dist-info/RECORD +127 -0
- dara_core-1.21.16.dist-info/RECORD +0 -127
- {dara_core-1.21.16.dist-info → dara_core-1.21.17.dist-info}/LICENSE +0 -0
- {dara_core-1.21.16.dist-info → dara_core-1.21.17.dist-info}/WHEEL +0 -0
- {dara_core-1.21.16.dist-info → dara_core-1.21.17.dist-info}/entry_points.txt +0 -0
dara/core/configuration.py
CHANGED
|
@@ -17,20 +17,13 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
import os
|
|
19
19
|
import pathlib
|
|
20
|
+
from collections.abc import Callable
|
|
20
21
|
from inspect import isclass, isfunction
|
|
21
22
|
from types import ModuleType
|
|
22
23
|
from typing import (
|
|
23
24
|
Any,
|
|
24
|
-
Callable,
|
|
25
|
-
Dict,
|
|
26
|
-
List,
|
|
27
25
|
Literal,
|
|
28
|
-
Optional,
|
|
29
|
-
Set,
|
|
30
|
-
Tuple,
|
|
31
|
-
Type,
|
|
32
26
|
TypeVar,
|
|
33
|
-
Union,
|
|
34
27
|
)
|
|
35
28
|
|
|
36
29
|
from fastapi.middleware import Middleware
|
|
@@ -75,34 +68,34 @@ class Configuration(BaseModel):
|
|
|
75
68
|
|
|
76
69
|
auth_config: BaseAuthConfig
|
|
77
70
|
registry_lookup: CustomRegistryLookup
|
|
78
|
-
actions:
|
|
79
|
-
endpoint_configurations:
|
|
80
|
-
components:
|
|
81
|
-
context_components:
|
|
71
|
+
actions: list[ActionDef]
|
|
72
|
+
endpoint_configurations: list[EndpointConfiguration]
|
|
73
|
+
components: list[ComponentTypeAnnotation]
|
|
74
|
+
context_components: list[ComponentInstance]
|
|
82
75
|
enable_devtools: bool
|
|
83
|
-
module_dependencies:
|
|
76
|
+
module_dependencies: dict[str, str]
|
|
84
77
|
live_reload: bool
|
|
85
78
|
powered_by_causalens: bool
|
|
86
79
|
router: Router
|
|
87
|
-
pages:
|
|
88
|
-
routes:
|
|
89
|
-
scheduled_jobs:
|
|
90
|
-
startup_functions:
|
|
91
|
-
static_folders:
|
|
80
|
+
pages: dict[str, Page]
|
|
81
|
+
routes: set[ApiRoute]
|
|
82
|
+
scheduled_jobs: list[tuple[ScheduledJob | ScheduledJobFactory, Callable, list[Any] | None]] = []
|
|
83
|
+
startup_functions: list[Callable]
|
|
84
|
+
static_folders: list[str]
|
|
92
85
|
static_files_dir: str
|
|
93
|
-
package_tag_processors:
|
|
86
|
+
package_tag_processors: list[Callable[[dict[str, list[str]]], dict[str, list[str]]]]
|
|
94
87
|
template_extra_js: str
|
|
95
|
-
task_module:
|
|
88
|
+
task_module: str | None = None
|
|
96
89
|
template: str
|
|
97
|
-
template_renderers:
|
|
98
|
-
theme:
|
|
90
|
+
template_renderers: dict[str, Callable[..., Template]]
|
|
91
|
+
theme: BaseTheme | str
|
|
99
92
|
title: str
|
|
100
|
-
ws_handlers:
|
|
101
|
-
encoders:
|
|
102
|
-
middlewares:
|
|
93
|
+
ws_handlers: dict[str, Callable[[str, Any], Any]]
|
|
94
|
+
encoders: dict[type[Any], Encoder]
|
|
95
|
+
middlewares: list[Middleware]
|
|
103
96
|
model_config = ConfigDict(extra='forbid', arbitrary_types_allowed=True)
|
|
104
97
|
|
|
105
|
-
def get_package_map(self) ->
|
|
98
|
+
def get_package_map(self) -> dict[str, str]:
|
|
106
99
|
"""
|
|
107
100
|
Get a map of python package names to js package names, based on currently
|
|
108
101
|
registered components, actions etc.
|
|
@@ -145,28 +138,28 @@ class ConfigurationBuilder:
|
|
|
145
138
|
|
|
146
139
|
auth_config: BaseAuthConfig
|
|
147
140
|
registry_lookup: CustomRegistryLookup
|
|
148
|
-
_actions:
|
|
149
|
-
_components:
|
|
150
|
-
_module_dependencies:
|
|
151
|
-
_errors:
|
|
141
|
+
_actions: list[ActionDef]
|
|
142
|
+
_components: list[ComponentTypeAnnotation]
|
|
143
|
+
_module_dependencies: dict[str, str]
|
|
144
|
+
_errors: list[str]
|
|
152
145
|
enable_devtools: bool
|
|
153
146
|
live_reload: bool
|
|
154
|
-
_pages:
|
|
155
|
-
_template_renderers:
|
|
156
|
-
_endpoint_configurations:
|
|
157
|
-
_static_folders:
|
|
158
|
-
_package_tags_processors:
|
|
147
|
+
_pages: dict[str, Page]
|
|
148
|
+
_template_renderers: dict[str, Callable[..., Template]]
|
|
149
|
+
_endpoint_configurations: list[EndpointConfiguration]
|
|
150
|
+
_static_folders: list[str]
|
|
151
|
+
_package_tags_processors: list[Callable[[dict[str, list[str]]], dict[str, list[str]]]]
|
|
159
152
|
_template_extra_js: str
|
|
160
|
-
_custom_ws_handlers:
|
|
161
|
-
_custom_encoders:
|
|
162
|
-
_middlewares:
|
|
163
|
-
routes:
|
|
153
|
+
_custom_ws_handlers: dict[str, Callable[[str, Any], Any]]
|
|
154
|
+
_custom_encoders: dict[type[Any], Encoder]
|
|
155
|
+
_middlewares: list[Middleware]
|
|
156
|
+
routes: set[ApiRoute]
|
|
164
157
|
router: Router
|
|
165
158
|
static_files_dir: str
|
|
166
|
-
scheduled_jobs:
|
|
167
|
-
startup_functions:
|
|
168
|
-
context_components:
|
|
169
|
-
task_module:
|
|
159
|
+
scheduled_jobs: list[tuple[ScheduledJob | ScheduledJobFactory, Callable, list[Any] | None]] = []
|
|
160
|
+
startup_functions: list[Callable]
|
|
161
|
+
context_components: list[ComponentInstance]
|
|
162
|
+
task_module: str | None
|
|
170
163
|
_template: str
|
|
171
164
|
theme: BaseTheme
|
|
172
165
|
title: str
|
|
@@ -224,7 +217,7 @@ class ConfigurationBuilder:
|
|
|
224
217
|
def powered_by_causalens(self, value):
|
|
225
218
|
self._powered_by_causalens = value
|
|
226
219
|
|
|
227
|
-
def add_action(self, action:
|
|
220
|
+
def add_action(self, action: type[ActionImpl], local: bool = False):
|
|
228
221
|
"""
|
|
229
222
|
Register an Action with the application.
|
|
230
223
|
|
|
@@ -276,7 +269,7 @@ class ConfigurationBuilder:
|
|
|
276
269
|
self.context_components.append(component)
|
|
277
270
|
self.add_component(component.__class__)
|
|
278
271
|
|
|
279
|
-
def add_component(self, component:
|
|
272
|
+
def add_component(self, component: type[ComponentInstance], local: bool = False):
|
|
280
273
|
"""
|
|
281
274
|
Register a Component with the application.
|
|
282
275
|
|
|
@@ -381,7 +374,7 @@ class ConfigurationBuilder:
|
|
|
381
374
|
EncoderType = TypeVar('EncoderType')
|
|
382
375
|
|
|
383
376
|
def add_encoder(
|
|
384
|
-
self, typ:
|
|
377
|
+
self, typ: type[EncoderType], serialize: Callable[[EncoderType], Any], deserialize: Callable[[Any], EncoderType]
|
|
385
378
|
):
|
|
386
379
|
"""
|
|
387
380
|
Register a custom encoder, which serialize and deserialize the type
|
|
@@ -398,7 +391,7 @@ class ConfigurationBuilder:
|
|
|
398
391
|
self._custom_encoders[typ] = encoder
|
|
399
392
|
return encoder
|
|
400
393
|
|
|
401
|
-
def add_package_tags_processor(self, processor: Callable[[
|
|
394
|
+
def add_package_tags_processor(self, processor: Callable[[dict[str, list[str]]], dict[str, list[str]]]):
|
|
402
395
|
"""
|
|
403
396
|
Append a package tag processor. This is a function that takes a dictionary of package names to lists of script/link tags included
|
|
404
397
|
when running in the UMD mode.
|
|
@@ -411,12 +404,12 @@ class ConfigurationBuilder:
|
|
|
411
404
|
def add_page(
|
|
412
405
|
self,
|
|
413
406
|
name: str,
|
|
414
|
-
content:
|
|
415
|
-
icon:
|
|
416
|
-
route:
|
|
417
|
-
include_in_menu:
|
|
418
|
-
reset_vars_on_load:
|
|
419
|
-
on_load:
|
|
407
|
+
content: ComponentInstanceType | type[CallableClassComponent] | str,
|
|
408
|
+
icon: str | None = None,
|
|
409
|
+
route: str | None = None,
|
|
410
|
+
include_in_menu: bool | None = True,
|
|
411
|
+
reset_vars_on_load: list[AnyVariable] | None = None,
|
|
412
|
+
on_load: Action | None = None,
|
|
420
413
|
):
|
|
421
414
|
"""
|
|
422
415
|
Add a new page to the layout of the platform. Switching between pages relies on the template implementing a
|
|
@@ -508,7 +501,7 @@ class ConfigurationBuilder:
|
|
|
508
501
|
|
|
509
502
|
return registry_lookup
|
|
510
503
|
|
|
511
|
-
def add_middleware(self, middleware:
|
|
504
|
+
def add_middleware(self, middleware: type | Callable, **options: Any):
|
|
512
505
|
"""
|
|
513
506
|
Add a middleware to the application. The middleware can be a class or a callable.
|
|
514
507
|
"""
|
|
@@ -526,8 +519,8 @@ class ConfigurationBuilder:
|
|
|
526
519
|
|
|
527
520
|
def set_theme(
|
|
528
521
|
self,
|
|
529
|
-
main_theme:
|
|
530
|
-
base_theme:
|
|
522
|
+
main_theme: ThemeDef | ClientVariable | Literal['light'] | Literal['dark'] | None = None,
|
|
523
|
+
base_theme: Literal['light'] | Literal['dark'] | None = None,
|
|
531
524
|
):
|
|
532
525
|
"""
|
|
533
526
|
Sets the color theme of the app. Takes ThemeDef models for the app, and reverts
|
|
@@ -554,7 +547,7 @@ class ConfigurationBuilder:
|
|
|
554
547
|
"""
|
|
555
548
|
self.startup_functions.append(startup_function)
|
|
556
549
|
|
|
557
|
-
def scheduler(self, job: ScheduledJob, args:
|
|
550
|
+
def scheduler(self, job: ScheduledJob, args: None | list[Any] = None):
|
|
558
551
|
if args is None:
|
|
559
552
|
args = []
|
|
560
553
|
|
|
@@ -563,7 +556,7 @@ class ConfigurationBuilder:
|
|
|
563
556
|
|
|
564
557
|
return _wrapper_func
|
|
565
558
|
|
|
566
|
-
def _run_discovery(self, module:
|
|
559
|
+
def _run_discovery(self, module: ModuleType | dict):
|
|
567
560
|
"""
|
|
568
561
|
Run import discovery in a given module, adding actions and components found to the config
|
|
569
562
|
|
dara/core/css.py
CHANGED
|
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import Literal
|
|
18
|
+
from typing import Literal
|
|
19
19
|
|
|
20
20
|
# Re-export CSSProperties for easier importing
|
|
21
21
|
from dara.core.visual.css import CSSProperties # noqa: F401
|
|
@@ -27,7 +27,7 @@ IconSize = Literal['1x', '2x', '3x', '4x', '5x', '6x', '7x', '8x', '9x', '10x',
|
|
|
27
27
|
def get_icon(
|
|
28
28
|
name: str,
|
|
29
29
|
style: IconStyle = 'solid',
|
|
30
|
-
size:
|
|
30
|
+
size: IconSize | None = None,
|
|
31
31
|
):
|
|
32
32
|
"""
|
|
33
33
|
Get FontAwesome icon class string. Can be used for components requiring an icon name. The size be any one of the
|
dara/core/data_utils.py
CHANGED
|
@@ -17,7 +17,6 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
import io
|
|
19
19
|
import os
|
|
20
|
-
from typing import List, Optional, Union
|
|
21
20
|
|
|
22
21
|
import pandas
|
|
23
22
|
from pandas import DataFrame
|
|
@@ -75,7 +74,7 @@ class FileStore(BaseModel):
|
|
|
75
74
|
scope = get_cache_scope(cache_type)
|
|
76
75
|
return os.path.join(self.root_path, scope)
|
|
77
76
|
|
|
78
|
-
def list_files(self, cache_type: CacheType) ->
|
|
77
|
+
def list_files(self, cache_type: CacheType) -> list[str]:
|
|
79
78
|
"""
|
|
80
79
|
List files in a directory for a given cache type
|
|
81
80
|
|
|
@@ -101,7 +100,7 @@ class FileStore(BaseModel):
|
|
|
101
100
|
file_path = os.path.join(scope_path, name)
|
|
102
101
|
return os.path.exists(file_path)
|
|
103
102
|
|
|
104
|
-
def get_file(self, cache_type: CacheType, name: str) ->
|
|
103
|
+
def get_file(self, cache_type: CacheType, name: str) -> io.BufferedReader | None:
|
|
105
104
|
"""
|
|
106
105
|
Get a BufferedReader to read a file from the data store
|
|
107
106
|
|
|
@@ -160,7 +159,7 @@ class DataFactory(BaseModel):
|
|
|
160
159
|
file_store = FileStore(root_path=root_path)
|
|
161
160
|
super().__init__(file_store=file_store)
|
|
162
161
|
|
|
163
|
-
def list_datasets(self, cache: CacheType = CacheType.GLOBAL) ->
|
|
162
|
+
def list_datasets(self, cache: CacheType = CacheType.GLOBAL) -> list[str]:
|
|
164
163
|
"""
|
|
165
164
|
Get a list of datasets (filenames) available for a given cache type
|
|
166
165
|
|
|
@@ -171,9 +170,9 @@ class DataFactory(BaseModel):
|
|
|
171
170
|
|
|
172
171
|
def list_datasets_var(
|
|
173
172
|
self,
|
|
174
|
-
cache:
|
|
175
|
-
polling_interval:
|
|
176
|
-
) -> DerivedVariable[
|
|
173
|
+
cache: CacheType | ClientVariable = CacheType.GLOBAL,
|
|
174
|
+
polling_interval: int | None = None,
|
|
175
|
+
) -> DerivedVariable[list[str]]:
|
|
177
176
|
"""
|
|
178
177
|
Create a DerivedVariable which stores a list of datasets (filenames) available for a given cache type
|
|
179
178
|
|
|
@@ -262,7 +261,7 @@ class DataFactory(BaseModel):
|
|
|
262
261
|
"""
|
|
263
262
|
return os.path.join(self.file_store.get_scoped_path(cache), name)
|
|
264
263
|
|
|
265
|
-
def read_dataset(self, name: str, cache: CacheType = CacheType.GLOBAL) ->
|
|
264
|
+
def read_dataset(self, name: str, cache: CacheType = CacheType.GLOBAL) -> DataFrame | None:
|
|
266
265
|
"""
|
|
267
266
|
Read a dataset from disk to a DataFrame.
|
|
268
267
|
|
|
@@ -288,9 +287,9 @@ class DataFactory(BaseModel):
|
|
|
288
287
|
|
|
289
288
|
def read_dataset_var(
|
|
290
289
|
self,
|
|
291
|
-
name:
|
|
292
|
-
cache:
|
|
293
|
-
polling_interval:
|
|
290
|
+
name: str | ClientVariable,
|
|
291
|
+
cache: CacheType | ClientVariable = CacheType.GLOBAL,
|
|
292
|
+
polling_interval: int | None = None,
|
|
294
293
|
) -> DerivedVariable:
|
|
295
294
|
"""
|
|
296
295
|
Create a DerivedVariable which reads a specific dataset from disk
|
|
@@ -318,9 +317,7 @@ class DataFactory(BaseModel):
|
|
|
318
317
|
"""
|
|
319
318
|
self.file_store.delete_file(cache, name)
|
|
320
319
|
|
|
321
|
-
def delete_dataset_action(
|
|
322
|
-
self, name: Union[str, ClientVariable], cache: Union[CacheType, ClientVariable] = CacheType.GLOBAL
|
|
323
|
-
):
|
|
320
|
+
def delete_dataset_action(self, name: str | ClientVariable, cache: CacheType | ClientVariable = CacheType.GLOBAL):
|
|
324
321
|
"""
|
|
325
322
|
Get a SideEffect action which deletes a given dataset
|
|
326
323
|
|
|
@@ -332,9 +329,7 @@ class DataFactory(BaseModel):
|
|
|
332
329
|
|
|
333
330
|
return SideEffect(lambda ctx: self.delete_dataset(ctx.extras[0], ctx.extras[1]), extras=[name_var, cache_var])
|
|
334
331
|
|
|
335
|
-
def download_dataset_action(
|
|
336
|
-
self, name: Union[str, ClientVariable], cache: Union[CacheType, ClientVariable] = CacheType.GLOBAL
|
|
337
|
-
):
|
|
332
|
+
def download_dataset_action(self, name: str | ClientVariable, cache: CacheType | ClientVariable = CacheType.GLOBAL):
|
|
338
333
|
"""
|
|
339
334
|
Get a DownloadContent action which downloads a dataset with a given name as a .csv
|
|
340
335
|
|
dara/core/defaults.py
CHANGED
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from typing import TYPE_CHECKING,
|
|
20
|
+
from typing import TYPE_CHECKING, cast
|
|
21
21
|
|
|
22
22
|
from dara.core.base_definitions import ActionDef
|
|
23
23
|
from dara.core.interactivity.actions import (
|
|
@@ -76,7 +76,7 @@ INITIAL_CORE_INTERNALS = {'Store': _store}
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
# These components are provided by the core JS of this module
|
|
79
|
-
CORE_COMPONENTS:
|
|
79
|
+
CORE_COMPONENTS: dict[str, ComponentTypeAnnotation] = {
|
|
80
80
|
DynamicComponent.__name__: DynamicComponentDef,
|
|
81
81
|
Menu.__name__: MenuDef,
|
|
82
82
|
MenuLink.__name__: MenuLinkDef,
|
|
@@ -96,7 +96,7 @@ CORE_COMPONENTS: Dict[str, ComponentTypeAnnotation] = {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
# These actions are provided by the core JS of this module
|
|
99
|
-
CORE_ACTIONS:
|
|
99
|
+
CORE_ACTIONS: dict[str, ActionDef] = {
|
|
100
100
|
'NavigateTo': NavigateToDef,
|
|
101
101
|
'UpdateVariable': UpdateVariableDef,
|
|
102
102
|
TriggerVariable.__name__: TriggerVariableDef,
|
dara/core/definitions.py
CHANGED
|
@@ -19,19 +19,15 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import json
|
|
21
21
|
import uuid
|
|
22
|
-
from collections.abc import Awaitable, Mapping
|
|
22
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
23
23
|
from enum import Enum
|
|
24
24
|
from typing import (
|
|
25
|
+
Annotated,
|
|
25
26
|
Any,
|
|
26
|
-
Callable,
|
|
27
27
|
ClassVar,
|
|
28
|
-
List,
|
|
29
28
|
Literal,
|
|
30
|
-
Optional,
|
|
31
29
|
Protocol,
|
|
32
|
-
Type,
|
|
33
30
|
TypeVar,
|
|
34
|
-
Union,
|
|
35
31
|
runtime_checkable,
|
|
36
32
|
)
|
|
37
33
|
|
|
@@ -45,7 +41,6 @@ from pydantic import (
|
|
|
45
41
|
field_validator,
|
|
46
42
|
model_serializer,
|
|
47
43
|
)
|
|
48
|
-
from typing_extensions import Annotated
|
|
49
44
|
|
|
50
45
|
from dara.core.base_definitions import Action, ComponentType
|
|
51
46
|
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
@@ -64,7 +59,7 @@ class HttpMethod(Enum):
|
|
|
64
59
|
|
|
65
60
|
|
|
66
61
|
class Session(BaseModel):
|
|
67
|
-
session_id:
|
|
62
|
+
session_id: str | None = None
|
|
68
63
|
|
|
69
64
|
|
|
70
65
|
DEFAULT_ERROR_TITLE = 'Unexpected error occurred'
|
|
@@ -99,7 +94,7 @@ class ErrorHandlingConfig(BaseModel):
|
|
|
99
94
|
description: str = DEFAULT_ERROR_DESCRIPTION
|
|
100
95
|
"""Description to display in the error boundary"""
|
|
101
96
|
|
|
102
|
-
raw_css: Annotated[
|
|
97
|
+
raw_css: Annotated[Any | None, BeforeValidator(transform_raw_css)] = None
|
|
103
98
|
"""
|
|
104
99
|
Raw styling to apply to the displayed error boundary.
|
|
105
100
|
Accepts a CSSProperties, dict, str, or ClientVariable.
|
|
@@ -125,27 +120,27 @@ class ComponentInstance(BaseModel):
|
|
|
125
120
|
|
|
126
121
|
uid: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
|
127
122
|
|
|
128
|
-
js_module: ClassVar[
|
|
123
|
+
js_module: ClassVar[str | None] = None
|
|
129
124
|
"""
|
|
130
125
|
JS module including the implementation of the component.
|
|
131
126
|
|
|
132
127
|
Required for non-local components.
|
|
133
128
|
"""
|
|
134
129
|
|
|
135
|
-
py_component: ClassVar[
|
|
130
|
+
py_component: ClassVar[str | None] = None
|
|
136
131
|
"""
|
|
137
132
|
Python unique component name. If not set, defaults to the class name.
|
|
138
133
|
"""
|
|
139
134
|
|
|
140
|
-
js_component: ClassVar[
|
|
135
|
+
js_component: ClassVar[str | None] = None
|
|
141
136
|
"""
|
|
142
137
|
JS component name. If not set, defaults to the class name.
|
|
143
138
|
"""
|
|
144
139
|
|
|
145
|
-
required_routes: ClassVar[
|
|
140
|
+
required_routes: ClassVar[list[ApiRoute]] = []
|
|
146
141
|
"""List of routes the component depends on. Will be implicitly added to the app if this component is used"""
|
|
147
142
|
|
|
148
|
-
raw_css: Annotated[
|
|
143
|
+
raw_css: Annotated[Any | None, BeforeValidator(transform_raw_css)] = None
|
|
149
144
|
"""
|
|
150
145
|
Raw styling to apply to the component.
|
|
151
146
|
Can be an dict/CSSProperties instance representing the `styles` tag, a string injected directly into the CSS of the wrapping component,
|
|
@@ -172,25 +167,25 @@ class ComponentInstance(BaseModel):
|
|
|
172
167
|
```
|
|
173
168
|
"""
|
|
174
169
|
|
|
175
|
-
track_progress:
|
|
170
|
+
track_progress: bool | None = False
|
|
176
171
|
"""Whether to use ProgressTracker to display progress updates from a task the component is subscribed to"""
|
|
177
172
|
|
|
178
|
-
error_handler:
|
|
173
|
+
error_handler: ErrorHandlingConfig | None = None
|
|
179
174
|
"""Configure the error handling for the component"""
|
|
180
175
|
|
|
181
|
-
fallback:
|
|
176
|
+
fallback: BaseFallback | ComponentInstance | None = None
|
|
182
177
|
"""
|
|
183
178
|
Fallback component to render in place of the actual UI if it has not finished loading
|
|
184
179
|
"""
|
|
185
180
|
|
|
186
|
-
id_:
|
|
181
|
+
id_: str | None = None
|
|
187
182
|
"""
|
|
188
183
|
An optional unique identifier for the component, defaults to None
|
|
189
184
|
|
|
190
185
|
This is intended to help identify components with human-readable names in the serialized trees, and is also set as the `id` attribute of the DOM element
|
|
191
186
|
"""
|
|
192
187
|
|
|
193
|
-
for_:
|
|
188
|
+
for_: str | None = None
|
|
194
189
|
"""
|
|
195
190
|
An optional for attribute for the component, defaults to None
|
|
196
191
|
|
|
@@ -270,7 +265,7 @@ class CallableClassComponent(Protocol):
|
|
|
270
265
|
def __call__(self) -> ComponentInstance: ...
|
|
271
266
|
|
|
272
267
|
|
|
273
|
-
DiscoverTarget =
|
|
268
|
+
DiscoverTarget = Callable[..., ComponentInstance] | ComponentInstance | type[CallableClassComponent]
|
|
274
269
|
DiscoverT = TypeVar('DiscoverT', bound=DiscoverTarget)
|
|
275
270
|
|
|
276
271
|
|
|
@@ -335,32 +330,32 @@ class StyledComponentInstance(ComponentInstance):
|
|
|
335
330
|
:param width: the width of the component, can be an number, which will be converted to pixels, or a string
|
|
336
331
|
"""
|
|
337
332
|
|
|
338
|
-
align:
|
|
339
|
-
background:
|
|
340
|
-
basis:
|
|
333
|
+
align: AlignItems | None = None
|
|
334
|
+
background: str | None = None
|
|
335
|
+
basis: int | str | bool | None = None
|
|
341
336
|
bold: bool = False
|
|
342
|
-
border:
|
|
343
|
-
border_radius:
|
|
344
|
-
children:
|
|
345
|
-
color:
|
|
346
|
-
font:
|
|
347
|
-
font_size:
|
|
348
|
-
gap:
|
|
349
|
-
grow:
|
|
350
|
-
height:
|
|
351
|
-
hug:
|
|
337
|
+
border: str | None = None
|
|
338
|
+
border_radius: float | int | str | None = None
|
|
339
|
+
children: list[ComponentInstance] | None = None
|
|
340
|
+
color: str | None = None
|
|
341
|
+
font: str | None = None
|
|
342
|
+
font_size: str | None = None
|
|
343
|
+
gap: float | int | str | None = None
|
|
344
|
+
grow: int | str | float | bool | None = None
|
|
345
|
+
height: float | int | str | None = None
|
|
346
|
+
hug: bool | None = None
|
|
352
347
|
italic: bool = False
|
|
353
|
-
margin:
|
|
354
|
-
max_height:
|
|
355
|
-
max_width:
|
|
356
|
-
min_height:
|
|
357
|
-
min_width:
|
|
358
|
-
overflow:
|
|
359
|
-
position:
|
|
360
|
-
padding:
|
|
361
|
-
shrink:
|
|
348
|
+
margin: float | int | str | None = None
|
|
349
|
+
max_height: float | int | str | None = None
|
|
350
|
+
max_width: float | int | str | None = None
|
|
351
|
+
min_height: float | int | str | None = None
|
|
352
|
+
min_width: float | int | str | None = None
|
|
353
|
+
overflow: str | None = None
|
|
354
|
+
position: str | None = None
|
|
355
|
+
padding: float | int | str | None = None
|
|
356
|
+
shrink: int | str | float | bool | None = None
|
|
362
357
|
underline: bool = False
|
|
363
|
-
width:
|
|
358
|
+
width: float | int | str | None = None
|
|
364
359
|
|
|
365
360
|
@field_validator(
|
|
366
361
|
'height',
|
|
@@ -401,7 +396,7 @@ class StyledComponentInstance(ComponentInstance):
|
|
|
401
396
|
|
|
402
397
|
|
|
403
398
|
class BaseFallback(StyledComponentInstance):
|
|
404
|
-
suspend_render:
|
|
399
|
+
suspend_render: bool | int = 200
|
|
405
400
|
"""
|
|
406
401
|
:param suspend_render: bool or int, optional
|
|
407
402
|
Determines the suspense behavior of the component during state updates.
|
|
@@ -429,20 +424,20 @@ class BaseFallback(StyledComponentInstance):
|
|
|
429
424
|
|
|
430
425
|
ComponentInstance.model_rebuild()
|
|
431
426
|
|
|
432
|
-
ComponentInstanceType =
|
|
427
|
+
ComponentInstanceType = ComponentInstance | Callable[..., ComponentInstance]
|
|
433
428
|
|
|
434
429
|
|
|
435
430
|
class JsComponentDef(BaseModel):
|
|
436
431
|
"""Definition of a JS Component"""
|
|
437
432
|
|
|
438
|
-
js_module:
|
|
433
|
+
js_module: str | None = None
|
|
439
434
|
"""
|
|
440
435
|
JS module where the component implementation lives.
|
|
441
436
|
|
|
442
437
|
Not required for local components as they are located via dara.config.json
|
|
443
438
|
"""
|
|
444
439
|
|
|
445
|
-
js_component:
|
|
440
|
+
js_component: str | None = None
|
|
446
441
|
"""
|
|
447
442
|
JS component name. If not set, defaults to `name` property.
|
|
448
443
|
"""
|
|
@@ -459,11 +454,11 @@ class JsComponentDef(BaseModel):
|
|
|
459
454
|
class PyComponentDef(BaseModel):
|
|
460
455
|
"""Definition of a Python Component"""
|
|
461
456
|
|
|
462
|
-
func:
|
|
457
|
+
func: Callable[..., Any] | None = None
|
|
463
458
|
name: str
|
|
464
|
-
dynamic_kwargs:
|
|
465
|
-
fallback:
|
|
466
|
-
polling_interval:
|
|
459
|
+
dynamic_kwargs: Mapping[str, AnyVariable] | None = None
|
|
460
|
+
fallback: BaseFallback | ComponentInstance | None = None
|
|
461
|
+
polling_interval: int | None = None
|
|
467
462
|
render_component: Callable[..., Awaitable[Any]]
|
|
468
463
|
"""Handler to render the component. Defaults to dara.core.visual.dynamic_component.render_component"""
|
|
469
464
|
|
|
@@ -488,7 +483,7 @@ class PyComponentDef(BaseModel):
|
|
|
488
483
|
|
|
489
484
|
|
|
490
485
|
# Helper type annotation for working with components
|
|
491
|
-
ComponentTypeAnnotation =
|
|
486
|
+
ComponentTypeAnnotation = PyComponentDef | JsComponentDef
|
|
492
487
|
|
|
493
488
|
|
|
494
489
|
class EndpointConfiguration(BaseModel):
|
|
@@ -507,7 +502,7 @@ class EndpointConfiguration(BaseModel):
|
|
|
507
502
|
class ApiRoute(BaseModel):
|
|
508
503
|
"""Definition of a route for the application's api"""
|
|
509
504
|
|
|
510
|
-
dependencies:
|
|
505
|
+
dependencies: list[Depends] = []
|
|
511
506
|
handler: Callable
|
|
512
507
|
method: HttpMethod
|
|
513
508
|
url: str
|
|
@@ -520,13 +515,13 @@ class ApiRoute(BaseModel):
|
|
|
520
515
|
class Page(BaseModel):
|
|
521
516
|
"""Definition of a Page"""
|
|
522
517
|
|
|
523
|
-
icon:
|
|
518
|
+
icon: str | None = None
|
|
524
519
|
content: ComponentInstanceType
|
|
525
520
|
name: str
|
|
526
|
-
sub_pages:
|
|
521
|
+
sub_pages: list[Page] | None = []
|
|
527
522
|
url_safe_name: str
|
|
528
|
-
include_in_menu:
|
|
529
|
-
on_load:
|
|
523
|
+
include_in_menu: bool | None = None
|
|
524
|
+
on_load: Action | None = None
|
|
530
525
|
model_config = ConfigDict(extra='forbid')
|
|
531
526
|
|
|
532
527
|
|
|
@@ -534,17 +529,17 @@ class TemplateRoute(BaseModel):
|
|
|
534
529
|
"""Definition of a route for the TemplateRouter"""
|
|
535
530
|
|
|
536
531
|
content: ComponentInstance
|
|
537
|
-
icon:
|
|
532
|
+
icon: str | None = None
|
|
538
533
|
name: str
|
|
539
534
|
route: str
|
|
540
|
-
include_in_menu:
|
|
541
|
-
on_load:
|
|
535
|
+
include_in_menu: bool | None = None
|
|
536
|
+
on_load: Action | None = None
|
|
542
537
|
|
|
543
538
|
|
|
544
539
|
class TemplateRouterLink(BaseModel):
|
|
545
540
|
"""Definition of a link for the TemplateRouter"""
|
|
546
541
|
|
|
547
|
-
icon:
|
|
542
|
+
icon: str | None = None
|
|
548
543
|
name: str
|
|
549
544
|
route: str
|
|
550
545
|
|
|
@@ -554,8 +549,8 @@ class TemplateRouterContent(BaseModel):
|
|
|
554
549
|
|
|
555
550
|
content: ComponentInstance
|
|
556
551
|
route: str
|
|
557
|
-
on_load:
|
|
558
|
-
name:
|
|
552
|
+
on_load: Action | None = None
|
|
553
|
+
name: str | None = None
|
|
559
554
|
|
|
560
555
|
|
|
561
556
|
class Template(BaseModel):
|
dara/core/http.py
CHANGED
|
@@ -17,8 +17,8 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
import inspect
|
|
19
19
|
from collections import OrderedDict
|
|
20
|
+
from collections.abc import Callable
|
|
20
21
|
from functools import wraps
|
|
21
|
-
from typing import Callable, Dict, List, Type, Union
|
|
22
22
|
|
|
23
23
|
from fastapi import Depends
|
|
24
24
|
from fastapi.params import Depends as DependsType
|
|
@@ -26,7 +26,7 @@ from fastapi.params import Depends as DependsType
|
|
|
26
26
|
from dara.core.definitions import ApiRoute, EndpointConfiguration, HttpMethod
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def _get_config_instances(annotations:
|
|
29
|
+
def _get_config_instances(annotations: dict[str, type]) -> dict[str, EndpointConfiguration]:
|
|
30
30
|
"""
|
|
31
31
|
Get EndpointConfiguration instances to inject given the function annotations
|
|
32
32
|
|
|
@@ -54,7 +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:
|
|
57
|
+
def _decorator(url: str, dependencies: list[DependsType] | None = None, authenticated: bool = True):
|
|
58
58
|
if dependencies is None:
|
|
59
59
|
dependencies = []
|
|
60
60
|
|
|
@@ -73,7 +73,7 @@ def _method_decorator(method: HttpMethod):
|
|
|
73
73
|
new_annotations = {}
|
|
74
74
|
params = OrderedDict()
|
|
75
75
|
|
|
76
|
-
configurations:
|
|
76
|
+
configurations: list[type[EndpointConfiguration]] = []
|
|
77
77
|
sig = inspect.signature(func)
|
|
78
78
|
for var_name, typ in func.__annotations__.items():
|
|
79
79
|
if inspect.isclass(typ) and issubclass(typ, EndpointConfiguration):
|