dara-components 1.8.5__py3-none-any.whl → 1.22.1__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/components/__init__.py +18 -0
- dara/components/_assets/__init__.py +30 -0
- dara/components/_assets/auto_js/.gitkeep +0 -0
- dara/components/_assets/auto_js/dara.components.css +1494 -0
- dara/components/_assets/auto_js/dara.components.umd.js +182837 -0
- dara/components/_assets/common/bokeh-3.1.1.min.js +690 -0
- dara/components/_assets/common/bokeh-api-3.1.1.min.js +60 -0
- dara/components/_assets/common/bokeh-gl-3.1.1.min.js +67 -0
- dara/components/_assets/common/bokeh-mathjax-3.1.1.min.js +329 -0
- dara/components/_assets/common/bokeh-tables-3.1.1.min.js +132 -0
- dara/components/_assets/common/bokeh-widgets-3.1.1.min.js +129 -0
- dara/components/_assets/common/pixi-filters.min.js +17 -0
- dara/components/_assets/common/pixi.min.js +2214 -0
- dara/components/_assets/common/pixi_viewport.js +1 -0
- dara/components/_assets/common/plotly.min.js +8 -0
- dara/components/common/__init__.py +11 -2
- dara/components/common/accordion.py +20 -26
- dara/components/common/anchor.py +9 -10
- dara/components/common/base_component.py +23 -36
- dara/components/common/bullet_list.py +1 -3
- dara/components/common/button.py +35 -26
- dara/components/common/button_bar.py +25 -20
- dara/components/common/card.py +4 -5
- dara/components/common/carousel.py +9 -9
- dara/components/common/checkbox_group.py +26 -19
- dara/components/common/code.py +8 -5
- dara/components/common/component_select_list.py +9 -13
- dara/components/common/datepicker.py +16 -16
- dara/components/common/dropdown_menu.py +161 -0
- dara/components/common/dropzone.py +42 -33
- dara/components/common/form.py +5 -7
- dara/components/common/form_page.py +4 -6
- dara/components/common/grid.py +21 -18
- dara/components/common/heading.py +5 -4
- dara/components/common/icon.py +1 -3
- dara/components/common/if_cmp.py +23 -17
- dara/components/common/image.py +2 -2
- dara/components/common/input.py +9 -11
- dara/components/common/label.py +13 -14
- dara/components/common/markdown.py +3 -5
- dara/components/common/modal.py +2 -2
- dara/components/common/overlay.py +8 -14
- dara/components/common/paragraph.py +2 -2
- dara/components/common/progress_bar.py +6 -8
- dara/components/common/radio_group.py +38 -21
- dara/components/common/select.py +33 -30
- dara/components/common/slider.py +74 -29
- dara/components/common/spacer.py +4 -6
- dara/components/common/stack.py +7 -4
- dara/components/common/switch.py +6 -8
- dara/components/common/tabbed_card.py +8 -11
- dara/components/common/table.py +224 -73
- dara/components/common/text.py +7 -9
- dara/components/common/textarea.py +7 -7
- dara/components/common/time_utils.py +2 -5
- dara/components/common/tooltip.py +4 -6
- dara/components/common/utils.py +29 -35
- dara/components/graphs/__init__.py +1 -0
- dara/components/graphs/components/base_graph_component.py +34 -22
- dara/components/graphs/components/causal_graph_viewer.py +13 -15
- dara/components/graphs/components/edge_encoder.py +49 -26
- dara/components/graphs/components/node_hierarchy_builder.py +17 -16
- dara/components/graphs/definitions.py +27 -20
- dara/components/graphs/graph_layout.py +90 -53
- dara/components/plotting/__init__.py +2 -1
- dara/components/plotting/bokeh/bokeh.py +7 -10
- dara/components/plotting/bokeh/utils.py +5 -3
- dara/components/plotting/plotly/plotly.py +24 -19
- dara/components/plotting/plotly/themes.py +7 -5
- dara/components/smart/__init__.py +7 -1
- dara/components/smart/chat/chat.py +7 -8
- dara/components/smart/chat/config.py +1 -1
- dara/components/smart/chat/types.py +4 -6
- dara/components/smart/code_editor/code_editor.py +18 -4
- dara/components/smart/code_editor/util.py +11 -11
- dara/components/smart/data_slicer/__init__.py +4 -0
- dara/components/smart/data_slicer/data_slicer.py +14 -18
- dara/components/smart/data_slicer/data_slicer_modal.py +4 -6
- dara/components/smart/data_slicer/extension/data_slicer_filter.py +3 -4
- dara/components/smart/data_slicer/extension/filter_status_button.py +1 -3
- dara/components/smart/data_slicer/utils/core.py +23 -23
- dara/components/smart/data_slicer/utils/data_preview.py +1 -3
- dara/components/smart/data_slicer/utils/plotting.py +8 -6
- dara/components/smart/hierarchy.py +9 -10
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/METADATA +7 -7
- dara_components-1.22.1.dist-info/RECORD +100 -0
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/WHEEL +1 -1
- dara_components-1.22.1.dist-info/entry_points.txt +3 -0
- dara/components/umd/dara.components.umd.js +0 -396288
- dara/components/umd/style.css +0 -745
- dara_components-1.8.5.dist-info/RECORD +0 -86
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/LICENSE +0 -0
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
import ast
|
|
19
|
-
from typing import Any
|
|
19
|
+
from typing import Any
|
|
20
20
|
|
|
21
21
|
DEFAULT_WHITELIST = [
|
|
22
22
|
# Inbuilts
|
|
@@ -41,7 +41,7 @@ class ScriptVisitor(ast.NodeVisitor):
|
|
|
41
41
|
|
|
42
42
|
_function_blacklist = ['read_pickle', 'read_csv', 'read_fwf']
|
|
43
43
|
|
|
44
|
-
def __init__(self, undeclared_whitelist:
|
|
44
|
+
def __init__(self, undeclared_whitelist: list[str]):
|
|
45
45
|
self.undeclared_whitelist = undeclared_whitelist
|
|
46
46
|
self.declared_vars: list = []
|
|
47
47
|
super().__init__()
|
|
@@ -63,9 +63,9 @@ class ScriptVisitor(ast.NodeVisitor):
|
|
|
63
63
|
self.declared_vars.append(target.id)
|
|
64
64
|
self.generic_visit(node)
|
|
65
65
|
|
|
66
|
-
def visit_Attribute(self,
|
|
67
|
-
self._check_dunder(
|
|
68
|
-
self.generic_visit(
|
|
66
|
+
def visit_Attribute(self, node):
|
|
67
|
+
self._check_dunder(node, node.attr)
|
|
68
|
+
self.generic_visit(node)
|
|
69
69
|
|
|
70
70
|
def visit_FunctionDef(self, node):
|
|
71
71
|
self._check_dunder(node, node.name)
|
|
@@ -89,7 +89,7 @@ class ScriptVisitor(ast.NodeVisitor):
|
|
|
89
89
|
self.generic_visit(node)
|
|
90
90
|
|
|
91
91
|
def visit_Call(self, node):
|
|
92
|
-
func_name:
|
|
92
|
+
func_name: str | None = None
|
|
93
93
|
if isinstance(node.func, ast.Name):
|
|
94
94
|
func_name = node.func.id
|
|
95
95
|
elif isinstance(node.func, ast.Attribute):
|
|
@@ -106,7 +106,7 @@ class ScriptVisitor(ast.NodeVisitor):
|
|
|
106
106
|
raise SyntaxError(f'Imports are not allowed: {node.names}')
|
|
107
107
|
|
|
108
108
|
|
|
109
|
-
def run_script(script: str, injections: dict =
|
|
109
|
+
def run_script(script: str, injections: dict | None = None, whitelist: list[str] = DEFAULT_WHITELIST) -> Any:
|
|
110
110
|
"""
|
|
111
111
|
Run a given script in a "sandbox".
|
|
112
112
|
Disallows imports, most globals except whitelisted ones.
|
|
@@ -131,13 +131,13 @@ def run_script(script: str, injections: dict = {}, whitelist: List[str] = DEFAUL
|
|
|
131
131
|
|
|
132
132
|
"""
|
|
133
133
|
# Validate that the script is safe
|
|
134
|
+
if injections is None:
|
|
135
|
+
injections = {}
|
|
134
136
|
module: ast.Module = ast.parse(script)
|
|
135
137
|
visitor = ScriptVisitor([*whitelist, *injections.keys()])
|
|
136
138
|
visitor.visit(module)
|
|
137
139
|
|
|
138
140
|
# Run the script
|
|
139
141
|
loc: dict = {}
|
|
140
|
-
exec(
|
|
141
|
-
|
|
142
|
-
) # nosec B102 # this is unsafe but we make best effort with the above to make it as safe as possible
|
|
143
|
-
return loc.get('return_val', None)
|
|
142
|
+
exec(script, injections, loc) # nosec B102 # this is unsafe but we make best effort with the above to make it as safe as possible
|
|
143
|
+
return loc.get('return_val')
|
|
@@ -17,8 +17,12 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
from dara.components.smart.data_slicer.data_slicer import DataSlicer
|
|
19
19
|
from dara.components.smart.data_slicer.data_slicer_modal import DataSlicerModal
|
|
20
|
+
from dara.components.smart.data_slicer.extension.filter_status_button import (
|
|
21
|
+
FilterStatusButton,
|
|
22
|
+
)
|
|
20
23
|
|
|
21
24
|
__all__ = [
|
|
22
25
|
'DataSlicer',
|
|
23
26
|
'DataSlicerModal',
|
|
27
|
+
'FilterStatusButton',
|
|
24
28
|
]
|
|
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import List, Union
|
|
19
|
-
|
|
20
18
|
from pandas import DataFrame
|
|
21
19
|
|
|
22
20
|
from dara.components import (
|
|
@@ -51,29 +49,29 @@ from dara.components.smart.data_slicer.utils.plotting import render_input_plot
|
|
|
51
49
|
from dara.core import DerivedVariable, Variable, py_component
|
|
52
50
|
from dara.core.actions import UpdateVariable
|
|
53
51
|
from dara.core.definitions import ComponentInstance, discover
|
|
54
|
-
from dara.core.interactivity import
|
|
52
|
+
from dara.core.interactivity import AnyVariable, ServerVariable
|
|
55
53
|
|
|
56
54
|
NO_RESULTS_FOUND = Stack(Text('No results found'))
|
|
57
55
|
TABLE_ROWS = 5
|
|
58
56
|
|
|
59
57
|
|
|
60
|
-
def increment(ctx: UpdateVariable.Ctx):
|
|
58
|
+
def increment(ctx: UpdateVariable.Ctx): # type: ignore
|
|
61
59
|
return ctx.inputs.old + 1
|
|
62
60
|
|
|
63
61
|
|
|
64
62
|
@discover
|
|
65
63
|
class DataSlicer:
|
|
66
|
-
def __init__(self, data:
|
|
64
|
+
def __init__(self, data: DataFrame | AnyVariable, rows_to_show: int = 10):
|
|
67
65
|
"""
|
|
68
66
|
DataSlicer component allows the user to select a subset of a dataset by variable ranges or individual rows.
|
|
69
|
-
Once instantiated, the `
|
|
67
|
+
Once instantiated, the `DerivedVariable` returned by `get_output()` will contain the filtered data.
|
|
70
68
|
|
|
71
69
|
Displayed inline.
|
|
72
70
|
|
|
73
71
|
:param data: input data
|
|
74
72
|
:param rows_to_show: number of rows to show in the 'Head' and 'Tail' sections of filter preview
|
|
75
73
|
"""
|
|
76
|
-
self.data_var = data if isinstance(data,
|
|
74
|
+
self.data_var = data if isinstance(data, AnyVariable) else ServerVariable(data)
|
|
77
75
|
self.selected_column = Variable(None)
|
|
78
76
|
self.rows_to_show = Variable(rows_to_show)
|
|
79
77
|
|
|
@@ -82,14 +80,12 @@ class DataSlicer:
|
|
|
82
80
|
self.table_columns = DerivedVariable(get_columns, variables=[self.column_definitions])
|
|
83
81
|
|
|
84
82
|
self.current_variable_filters = Variable([])
|
|
85
|
-
self.preview_output =
|
|
86
|
-
apply_filters, variables=[self.current_variable_filters, self.data_var]
|
|
87
|
-
)
|
|
83
|
+
self.preview_output = DerivedVariable(apply_filters, variables=[self.current_variable_filters, self.data_var])
|
|
88
84
|
|
|
89
85
|
# Table preview outputs
|
|
90
|
-
self.describe_data =
|
|
91
|
-
self.head_data =
|
|
92
|
-
self.tail_data =
|
|
86
|
+
self.describe_data = DerivedVariable(get_describe_data, variables=[self.preview_output])
|
|
87
|
+
self.head_data = DerivedVariable(get_head_data, variables=[self.preview_output, self.rows_to_show])
|
|
88
|
+
self.tail_data = DerivedVariable(get_tail_data, variables=[self.preview_output, self.rows_to_show])
|
|
93
89
|
|
|
94
90
|
# This is a workaround for issues in DO-230
|
|
95
91
|
self.manual_output_trigger = Variable(0)
|
|
@@ -99,20 +95,20 @@ class DataSlicer:
|
|
|
99
95
|
variables=[self.current_variable_filters, self.manual_output_trigger],
|
|
100
96
|
deps=[self.manual_output_trigger],
|
|
101
97
|
)
|
|
102
|
-
self.final_output =
|
|
98
|
+
self.final_output = DerivedVariable(
|
|
103
99
|
lambda x, _y: x,
|
|
104
100
|
variables=[self.preview_output, self.manual_output_trigger],
|
|
105
101
|
deps=[self.manual_output_trigger],
|
|
106
102
|
)
|
|
107
103
|
|
|
108
|
-
def get_output(self) ->
|
|
104
|
+
def get_output(self) -> DerivedVariable:
|
|
109
105
|
"""
|
|
110
106
|
Get the DerivedVariable containing filtered data
|
|
111
107
|
"""
|
|
112
108
|
return self.final_output
|
|
113
109
|
|
|
114
110
|
@py_component
|
|
115
|
-
def describe_table(self, columns:
|
|
111
|
+
def describe_table(self, columns: list[Column]):
|
|
116
112
|
"""
|
|
117
113
|
Display data.describe() as a Table
|
|
118
114
|
"""
|
|
@@ -122,14 +118,14 @@ class DataSlicer:
|
|
|
122
118
|
return Table(data=self.describe_data, columns=cols, max_rows=TABLE_ROWS)
|
|
123
119
|
|
|
124
120
|
@py_component
|
|
125
|
-
def table_head(self, columns:
|
|
121
|
+
def table_head(self, columns: list[Column]):
|
|
126
122
|
"""
|
|
127
123
|
Display data.head() as a Table
|
|
128
124
|
"""
|
|
129
125
|
return Table(data=self.head_data, columns=columns, max_rows=TABLE_ROWS)
|
|
130
126
|
|
|
131
127
|
@py_component
|
|
132
|
-
def table_tail(self, columns:
|
|
128
|
+
def table_tail(self, columns: list[Column]):
|
|
133
129
|
"""
|
|
134
130
|
Display data.tail() as a Table
|
|
135
131
|
"""
|
|
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import Union
|
|
19
|
-
|
|
20
18
|
from pandas import DataFrame
|
|
21
19
|
|
|
22
20
|
from dara.components.common import Button, Heading, Modal, Stack
|
|
@@ -30,11 +28,11 @@ from dara.core.definitions import ComponentInstance, discover
|
|
|
30
28
|
from dara.core.interactivity import AnyDataVariable, DerivedVariable, Variable
|
|
31
29
|
|
|
32
30
|
|
|
33
|
-
def toggle_variable(ctx: UpdateVariable.Ctx):
|
|
31
|
+
def toggle_variable(ctx: UpdateVariable.Ctx): # type: ignore
|
|
34
32
|
return not ctx.inputs.old
|
|
35
33
|
|
|
36
34
|
|
|
37
|
-
def increment(ctx: UpdateVariable.Ctx):
|
|
35
|
+
def increment(ctx: UpdateVariable.Ctx): # type: ignore
|
|
38
36
|
return ctx.inputs.old + 1
|
|
39
37
|
|
|
40
38
|
|
|
@@ -42,14 +40,14 @@ def increment(ctx: UpdateVariable.Ctx):
|
|
|
42
40
|
class DataSlicerModal(DataSlicer):
|
|
43
41
|
def __init__(
|
|
44
42
|
self,
|
|
45
|
-
data:
|
|
43
|
+
data: DataFrame | AnyDataVariable,
|
|
46
44
|
rows_to_show: int = 10,
|
|
47
45
|
button_top_position: str = '5%',
|
|
48
46
|
):
|
|
49
47
|
"""
|
|
50
48
|
DataSlicerModal component is a modal version of the DataSlicer component.
|
|
51
49
|
|
|
52
|
-
Once instantiated, the `
|
|
50
|
+
Once instantiated, the `DerivedVariable` returned by `get_output()` will contain the filtered data.
|
|
53
51
|
|
|
54
52
|
When included in a page, it adds a Filter button to the top-right corner of the screen which
|
|
55
53
|
displays current filter status when hovered. The button opens up a modal with the DataSlicer when clicked.
|
|
@@ -16,11 +16,10 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from enum import Enum
|
|
19
|
-
from typing import List, Optional
|
|
20
19
|
|
|
21
|
-
from pydantic import BaseModel
|
|
22
20
|
from typing_extensions import TypedDict
|
|
23
21
|
|
|
22
|
+
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
24
23
|
from dara.core.definitions import ComponentInstance
|
|
25
24
|
from dara.core.interactivity import AnyVariable, Variable
|
|
26
25
|
|
|
@@ -61,6 +60,6 @@ class DataSlicerFilter(ComponentInstance):
|
|
|
61
60
|
|
|
62
61
|
js_module = '@darajs/components'
|
|
63
62
|
|
|
64
|
-
filters: Variable[
|
|
63
|
+
filters: Variable[list[FilterInstance]]
|
|
65
64
|
columns: AnyVariable
|
|
66
|
-
height:
|
|
65
|
+
height: str | None = None
|
|
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import Optional
|
|
19
|
-
|
|
20
18
|
from typing_extensions import TypedDict
|
|
21
19
|
|
|
22
20
|
from dara.core.base_definitions import Action
|
|
@@ -45,4 +43,4 @@ class FilterStatusButton(ComponentInstance):
|
|
|
45
43
|
|
|
46
44
|
filter_stats: AnyVariable
|
|
47
45
|
on_click: Action
|
|
48
|
-
top_position:
|
|
46
|
+
top_position: str | None = '5%'
|
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
import re
|
|
19
19
|
from datetime import datetime, timezone
|
|
20
|
-
from typing import Any,
|
|
20
|
+
from typing import Any, Optional, cast
|
|
21
21
|
|
|
22
22
|
import numpy
|
|
23
23
|
from pandas import DataFrame, Series
|
|
@@ -60,17 +60,17 @@ def infer_column_type(data: DataFrame, col: str) -> ColumnType:
|
|
|
60
60
|
return ColumnType.CATEGORICAL
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
def get_column_definitions(data: DataFrame) ->
|
|
64
|
-
symbols:
|
|
63
|
+
def get_column_definitions(data: DataFrame) -> list[ColumnDefinition]:
|
|
64
|
+
symbols: list[str] = data.columns.values.tolist()
|
|
65
65
|
|
|
66
66
|
return [ColumnDefinition(name=s, type=infer_column_type(data, s)) for s in symbols if s != '__index__']
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
def get_column_items(column_defs:
|
|
69
|
+
def get_column_items(column_defs: list[ColumnDefinition]) -> list:
|
|
70
70
|
return [{'label': c['name'], 'value': c['name']} for c in column_defs]
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
def isnumber(*values:
|
|
73
|
+
def isnumber(*values: str | float):
|
|
74
74
|
"""
|
|
75
75
|
Check if all values are numeric strings (ints, floats etc)
|
|
76
76
|
"""
|
|
@@ -83,7 +83,7 @@ def isnumber(*values: Union[str, float]):
|
|
|
83
83
|
return True
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def apply_range_filter(range_filter: str, column: Series) -> Optional['Series
|
|
86
|
+
def apply_range_filter(range_filter: str, column: Series) -> Optional['Series']:
|
|
87
87
|
"""
|
|
88
88
|
Apply a 'range' filter on a column
|
|
89
89
|
|
|
@@ -93,7 +93,7 @@ def apply_range_filter(range_filter: str, column: Series) -> Optional['Series[bo
|
|
|
93
93
|
final_range_filter = None
|
|
94
94
|
|
|
95
95
|
# Look for groups of [<something>]
|
|
96
|
-
ranges:
|
|
96
|
+
ranges: list[str] = re.findall(r'\[[^\[\]]+\]', range_filter)
|
|
97
97
|
|
|
98
98
|
for rang in ranges:
|
|
99
99
|
if ',' not in rang:
|
|
@@ -107,8 +107,8 @@ def apply_range_filter(range_filter: str, column: Series) -> Optional['Series[bo
|
|
|
107
107
|
upper_raw = upper_raw.strip()
|
|
108
108
|
|
|
109
109
|
# Replace ':' symbols with (-)infinity
|
|
110
|
-
lower:
|
|
111
|
-
upper:
|
|
110
|
+
lower: str | float = float('-inf') if lower_raw == ':' else lower_raw
|
|
111
|
+
upper: str | float = float('inf') if upper_raw == ':' else upper_raw
|
|
112
112
|
|
|
113
113
|
# Only consider the range valid if the limits are numbers and lower < upper
|
|
114
114
|
if lower != '' and upper != '' and isnumber(lower, upper):
|
|
@@ -126,7 +126,7 @@ def apply_range_filter(range_filter: str, column: Series) -> Optional['Series[bo
|
|
|
126
126
|
return final_range_filter
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def apply_values_filter(values_filter: str, column: Series, col_type: ColumnType) -> Optional['Series
|
|
129
|
+
def apply_values_filter(values_filter: str, column: Series, col_type: ColumnType) -> Optional['Series']:
|
|
130
130
|
"""
|
|
131
131
|
Apply a 'values' filter on a column
|
|
132
132
|
|
|
@@ -135,7 +135,7 @@ def apply_values_filter(values_filter: str, column: Series, col_type: ColumnType
|
|
|
135
135
|
"""
|
|
136
136
|
final_values_filter = None
|
|
137
137
|
|
|
138
|
-
values:
|
|
138
|
+
values: list[Any] = (
|
|
139
139
|
[v.strip() for v in values_filter.split(',') if v != ''] if ',' in values_filter else [values_filter.strip()]
|
|
140
140
|
)
|
|
141
141
|
|
|
@@ -177,7 +177,7 @@ def parseISO(date: str) -> numpy.datetime64:
|
|
|
177
177
|
return numpy.datetime64(d)
|
|
178
178
|
|
|
179
179
|
|
|
180
|
-
def apply_date_filter(from_date: str, to_date: str, column: 'Series
|
|
180
|
+
def apply_date_filter(from_date: str, to_date: str, column: 'Series') -> Optional['Series']:
|
|
181
181
|
"""
|
|
182
182
|
Apply a 'from_date' and 'to_date' filters to a column
|
|
183
183
|
|
|
@@ -189,18 +189,18 @@ def apply_date_filter(from_date: str, to_date: str, column: 'Series[numpy.dateti
|
|
|
189
189
|
|
|
190
190
|
if from_date != '':
|
|
191
191
|
from_timestamp = parseISO(from_date)
|
|
192
|
-
from_date_filter = column.gt(from_timestamp)
|
|
192
|
+
from_date_filter = column.gt(from_timestamp) # type: ignore
|
|
193
193
|
final_date_filter = from_date_filter
|
|
194
194
|
|
|
195
195
|
if to_date != '':
|
|
196
196
|
to_timestamp = parseISO(to_date)
|
|
197
|
-
to_date_filter = column.lt(to_timestamp)
|
|
197
|
+
to_date_filter = column.lt(to_timestamp) # type: ignore
|
|
198
198
|
final_date_filter = final_date_filter & to_date_filter if final_date_filter is not None else to_date_filter
|
|
199
199
|
|
|
200
200
|
return final_date_filter
|
|
201
201
|
|
|
202
202
|
|
|
203
|
-
def apply_filters(variable_filters:
|
|
203
|
+
def apply_filters(variable_filters: list[FilterInstance], data: DataFrame) -> DataFrame:
|
|
204
204
|
"""
|
|
205
205
|
Apply filters on data
|
|
206
206
|
|
|
@@ -212,9 +212,9 @@ def apply_filters(variable_filters: List[FilterInstance], data: DataFrame) -> Da
|
|
|
212
212
|
for fil in variable_filters:
|
|
213
213
|
var = fil['column']
|
|
214
214
|
|
|
215
|
-
values_filter:
|
|
216
|
-
range_filter:
|
|
217
|
-
date_filter:
|
|
215
|
+
values_filter: Series | None = None
|
|
216
|
+
range_filter: Series | None = None
|
|
217
|
+
date_filter: Series | None = None
|
|
218
218
|
|
|
219
219
|
if var is None or var.strip() == '':
|
|
220
220
|
continue
|
|
@@ -223,14 +223,14 @@ def apply_filters(variable_filters: List[FilterInstance], data: DataFrame) -> Da
|
|
|
223
223
|
|
|
224
224
|
# Range filter
|
|
225
225
|
if fil['range'] != '' and 'range' in ALLOWED_FILTERS[column_type]:
|
|
226
|
-
range_filter = apply_range_filter(fil['range'], data[var])
|
|
226
|
+
range_filter = apply_range_filter(fil['range'], cast(Series, data[var]))
|
|
227
227
|
|
|
228
228
|
# Values filter
|
|
229
229
|
if fil['values'] != '' and 'values' in ALLOWED_FILTERS[column_type]:
|
|
230
|
-
values_filter = apply_values_filter(fil['values'], data[var], column_type)
|
|
230
|
+
values_filter = apply_values_filter(fil['values'], cast(Series, data[var]), column_type)
|
|
231
231
|
|
|
232
232
|
if (fil['from_date'] != '' or fil['to_date'] != '') and ('from_date' in ALLOWED_FILTERS[column_type]):
|
|
233
|
-
date_filter = apply_date_filter(fil['from_date'], fil['to_date'], data[var])
|
|
233
|
+
date_filter = apply_date_filter(fil['from_date'], fil['to_date'], cast(Series, data[var]))
|
|
234
234
|
|
|
235
235
|
# OR all of the defined filters together
|
|
236
236
|
final_filter = None
|
|
@@ -242,10 +242,10 @@ def apply_filters(variable_filters: List[FilterInstance], data: DataFrame) -> Da
|
|
|
242
242
|
if final_filter is not None:
|
|
243
243
|
output = output[final_filter]
|
|
244
244
|
|
|
245
|
-
return output
|
|
245
|
+
return cast(DataFrame, output)
|
|
246
246
|
|
|
247
247
|
|
|
248
|
-
def get_filter_stats(input_data: DataFrame, output_data: DataFrame, filters:
|
|
248
|
+
def get_filter_stats(input_data: DataFrame, output_data: DataFrame, filters: list[FilterInstance]) -> FilterStats:
|
|
249
249
|
"""
|
|
250
250
|
Get filter statistics
|
|
251
251
|
|
|
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import List
|
|
19
|
-
|
|
20
18
|
from pandas import DataFrame
|
|
21
19
|
|
|
22
20
|
from dara.components.common.table import Column, TableFormatterType
|
|
@@ -39,7 +37,7 @@ def get_tail_data(df: DataFrame, rows_to_show: int) -> DataFrame:
|
|
|
39
37
|
return df.tail(rows_to_show).fillna('NaN')
|
|
40
38
|
|
|
41
39
|
|
|
42
|
-
def get_columns(col_defs:
|
|
40
|
+
def get_columns(col_defs: list[ColumnDefinition]) -> list[Column]:
|
|
43
41
|
cols = []
|
|
44
42
|
|
|
45
43
|
for col_def in col_defs:
|
|
@@ -15,9 +15,11 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
from typing import cast
|
|
19
|
+
|
|
18
20
|
import numpy
|
|
19
21
|
from bokeh.plotting import figure
|
|
20
|
-
from pandas import DataFrame
|
|
22
|
+
from pandas import DataFrame, Series
|
|
21
23
|
from scipy.stats import gaussian_kde
|
|
22
24
|
|
|
23
25
|
from dara.components.common import Stack, Text
|
|
@@ -43,9 +45,9 @@ def _plot_x_numerical(dataset: DataFrame, x: str, **kwargs):
|
|
|
43
45
|
sizing_mode='stretch_both',
|
|
44
46
|
**kwargs,
|
|
45
47
|
)
|
|
46
|
-
p.toolbar.logo = None
|
|
48
|
+
p.toolbar.logo = None # type: ignore
|
|
47
49
|
|
|
48
|
-
pdf = gaussian_kde(df[x].dropna())
|
|
50
|
+
pdf = gaussian_kde(cast(DataFrame, df[x]).dropna())
|
|
49
51
|
y = pdf(lin)
|
|
50
52
|
p.line(
|
|
51
53
|
lin,
|
|
@@ -63,10 +65,10 @@ def _plot_x_categorical(dataset: DataFrame, x: str, **kwargs):
|
|
|
63
65
|
df = dataset.copy()
|
|
64
66
|
df = df[[x]].dropna().astype(str)
|
|
65
67
|
|
|
66
|
-
values_counts = df[x].value_counts()
|
|
68
|
+
values_counts = cast(Series, df[x]).value_counts()
|
|
67
69
|
|
|
68
70
|
p = figure(
|
|
69
|
-
x_range=sorted(list(df[x].unique())),
|
|
71
|
+
x_range=sorted(list(cast(Series, df[x]).unique())),
|
|
70
72
|
title=f'Histogram - {x}',
|
|
71
73
|
toolbar_location=None,
|
|
72
74
|
tools='',
|
|
@@ -76,7 +78,7 @@ def _plot_x_categorical(dataset: DataFrame, x: str, **kwargs):
|
|
|
76
78
|
|
|
77
79
|
p.vbar(x=values_counts.index, top=values_counts.values, width=0.5, color=BLUE)
|
|
78
80
|
|
|
79
|
-
p.toolbar.logo = None
|
|
81
|
+
p.toolbar.logo = None # type: ignore
|
|
80
82
|
|
|
81
83
|
p.xgrid.grid_line_color = None
|
|
82
84
|
|
|
@@ -15,13 +15,12 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
19
|
-
|
|
20
|
-
from pydantic import BaseModel
|
|
18
|
+
from typing import Optional
|
|
21
19
|
|
|
22
20
|
from dara.core.base_definitions import Action
|
|
21
|
+
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
23
22
|
from dara.core.definitions import StyledComponentInstance
|
|
24
|
-
from dara.core.interactivity import
|
|
23
|
+
from dara.core.interactivity import ClientVariable
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
class Node(BaseModel):
|
|
@@ -30,13 +29,13 @@ class Node(BaseModel):
|
|
|
30
29
|
are represented by stacking further Node components as children of a Node.
|
|
31
30
|
"""
|
|
32
31
|
|
|
33
|
-
children:
|
|
32
|
+
children: list['Node'] | None
|
|
34
33
|
id: str
|
|
35
34
|
label: str
|
|
36
35
|
weight: float
|
|
37
36
|
|
|
38
37
|
@staticmethod
|
|
39
|
-
def from_string(name: str, weight:
|
|
38
|
+
def from_string(name: str, weight: float | None = None, children: list['Node'] | None = None):
|
|
40
39
|
return Node(id=name, label=name, children=children, weight=weight if weight is not None else 0.0)
|
|
41
40
|
|
|
42
41
|
def find_node(self, target: str) -> Optional['Node']:
|
|
@@ -59,7 +58,7 @@ class Node(BaseModel):
|
|
|
59
58
|
return None
|
|
60
59
|
|
|
61
60
|
|
|
62
|
-
Node.
|
|
61
|
+
Node.model_rebuild()
|
|
63
62
|
|
|
64
63
|
|
|
65
64
|
class HierarchySelector(StyledComponentInstance):
|
|
@@ -74,7 +73,7 @@ class HierarchySelector(StyledComponentInstance):
|
|
|
74
73
|
allow_leaf_select: bool = True
|
|
75
74
|
hierarchy: Node
|
|
76
75
|
open_all: bool = True
|
|
77
|
-
value:
|
|
76
|
+
value: ClientVariable
|
|
78
77
|
|
|
79
78
|
|
|
80
79
|
class HierarchyViewer(StyledComponentInstance):
|
|
@@ -87,5 +86,5 @@ class HierarchyViewer(StyledComponentInstance):
|
|
|
87
86
|
|
|
88
87
|
allow_leaf_click: bool = True
|
|
89
88
|
allow_parent_click: bool = True
|
|
90
|
-
hierarchy:
|
|
91
|
-
on_click_node:
|
|
89
|
+
hierarchy: Node | ClientVariable
|
|
90
|
+
on_click_node: Action | None = None
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dara-components
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.22.1
|
|
4
4
|
Summary: Components for the Dara Framework
|
|
5
5
|
Home-page: https://dara.causalens.com/
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Author: Patricia Jacob
|
|
8
8
|
Author-email: patricia@causalens.com
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.10.0,<3.13.0
|
|
10
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Dist: bokeh (==3.1.1)
|
|
17
16
|
Requires-Dist: cai-causal-graph (>=0.3.6)
|
|
18
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: certifi (>=2024.7.4)
|
|
18
|
+
Requires-Dist: dara-core (==1.22.1)
|
|
19
19
|
Requires-Dist: dill (>=0.3.0,<0.4.0)
|
|
20
20
|
Requires-Dist: matplotlib (>=2.0.0)
|
|
21
21
|
Requires-Dist: pandas (>=1.1.0,<3.0.0)
|
|
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
|
|
28
28
|
# Dara Components
|
|
29
29
|
|
|
30
|
-
<img src="https://github.com/causalens/dara/blob/
|
|
30
|
+
<img src="https://github.com/causalens/dara/blob/v1.22.1/img/dara_light.svg?raw=true">
|
|
31
31
|
|
|
32
32
|

|
|
33
33
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|