meerschaum 3.0.0rc3__py3-none-any.whl → 3.0.0rc4__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.
- meerschaum/api/_events.py +5 -0
- meerschaum/api/dash/callbacks/dashboard.py +74 -97
- meerschaum/api/dash/callbacks/pipes.py +136 -57
- meerschaum/api/dash/callbacks/tokens.py +2 -1
- meerschaum/api/dash/components.py +6 -7
- meerschaum/api/dash/keys.py +17 -1
- meerschaum/api/dash/pages/pipes.py +14 -4
- meerschaum/api/dash/pipes.py +114 -29
- meerschaum/api/dash/tokens.py +1 -1
- meerschaum/config/_version.py +1 -1
- meerschaum/connectors/sql/_pipes.py +10 -5
- meerschaum/connectors/sql/tables/__init__.py +20 -3
- meerschaum/core/Pipe/__init__.py +17 -1
- meerschaum/utils/_get_pipes.py +30 -4
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/pipes.py +6 -2
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/METADATA +1 -1
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/RECORD +24 -24
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/licenses/NOTICE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc4.dist-info}/zip-safe +0 -0
meerschaum/api/_events.py
CHANGED
@@ -98,6 +98,11 @@ async def startup():
|
|
98
98
|
await shutdown()
|
99
99
|
os._exit(1)
|
100
100
|
|
101
|
+
conn = get_api_connector()
|
102
|
+
if conn.type == 'sql':
|
103
|
+
from meerschaum.connectors.sql.tables import get_tables
|
104
|
+
_ = get_tables(conn, refresh=True, create=True, debug=debug)
|
105
|
+
|
101
106
|
start_check_jobs_thread()
|
102
107
|
|
103
108
|
|
@@ -498,13 +498,9 @@ def update_flags(input_flags_dropdown_values, n_clicks, input_flags_texts):
|
|
498
498
|
|
499
499
|
@dash_app.callback(
|
500
500
|
Output('connector-keys-dropdown', 'options'),
|
501
|
-
Output('connector-keys-dropdown', 'value'),
|
502
501
|
Output('metric-keys-dropdown', 'options'),
|
503
|
-
Output('metric-keys-dropdown', 'value'),
|
504
502
|
Output('location-keys-dropdown', 'options'),
|
505
|
-
Output('location-keys-dropdown', 'value'),
|
506
503
|
Output('tags-dropdown', 'options'),
|
507
|
-
Output('tags-dropdown', 'value'),
|
508
504
|
Output('instance-select', 'value'),
|
509
505
|
Output('instance-alert-div', 'children'),
|
510
506
|
Input('connector-keys-dropdown', 'value'),
|
@@ -546,15 +542,6 @@ def update_keys_options(
|
|
546
542
|
except Exception as e:
|
547
543
|
instance_alerts += [alert_from_success_tuple((False, str(e)))]
|
548
544
|
|
549
|
-
### Update the keys filters.
|
550
|
-
if connector_keys is None:
|
551
|
-
connector_keys = []
|
552
|
-
if metric_keys is None:
|
553
|
-
metric_keys = []
|
554
|
-
if location_keys is None:
|
555
|
-
location_keys = []
|
556
|
-
if tags is None:
|
557
|
-
tags = []
|
558
545
|
num_filter = 0
|
559
546
|
if connector_keys:
|
560
547
|
num_filter += 1
|
@@ -565,10 +552,6 @@ def update_keys_options(
|
|
565
552
|
if tags:
|
566
553
|
num_filter += 1
|
567
554
|
|
568
|
-
_ck_filter = connector_keys
|
569
|
-
_mk_filter = metric_keys
|
570
|
-
_lk_filter = location_keys
|
571
|
-
_tags_filter = tags
|
572
555
|
_ck_alone = (connector_keys and num_filter == 1) or instance_click
|
573
556
|
_mk_alone = (metric_keys and num_filter == 1) or instance_click
|
574
557
|
_lk_alone = (location_keys and num_filter == 1) or instance_click
|
@@ -581,101 +564,95 @@ def update_keys_options(
|
|
581
564
|
_keys = fetch_pipes_keys(
|
582
565
|
'registered',
|
583
566
|
get_web_connector(ctx.states),
|
584
|
-
connector_keys=
|
585
|
-
metric_keys=
|
586
|
-
location_keys=
|
587
|
-
tags=
|
567
|
+
connector_keys=connector_keys,
|
568
|
+
metric_keys=metric_keys,
|
569
|
+
location_keys=location_keys,
|
570
|
+
tags=tags,
|
588
571
|
)
|
589
572
|
_tags_pipes = mrsm.get_pipes(
|
590
|
-
connector_keys=
|
591
|
-
metric_keys=
|
592
|
-
location_keys=
|
593
|
-
tags=
|
573
|
+
connector_keys=connector_keys,
|
574
|
+
metric_keys=metric_keys,
|
575
|
+
location_keys=location_keys,
|
576
|
+
tags=tags,
|
594
577
|
instance=get_web_connector(ctx.states),
|
595
578
|
as_tags_dict=True,
|
596
579
|
)
|
597
580
|
_all_tags = list(
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
581
|
+
set(
|
582
|
+
mrsm.get_pipes(
|
583
|
+
instance=get_web_connector(ctx.states),
|
584
|
+
as_tags_dict=True,
|
585
|
+
)
|
586
|
+
).union(tags or [])
|
602
587
|
) if _tags_alone else []
|
603
588
|
except Exception as e:
|
604
589
|
instance_alerts += [alert_from_success_tuple((False, str(e)))]
|
605
|
-
_all_keys, _keys = [], []
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
590
|
+
_all_keys, _all_tags, _keys = [], [], []
|
591
|
+
|
592
|
+
connectors_options = sorted(
|
593
|
+
list(
|
594
|
+
set(
|
595
|
+
keys_tuple[0] for keys_tuple in (_all_keys if _ck_alone else _keys)
|
596
|
+
).union(set(connector_keys or []))
|
597
|
+
),
|
598
|
+
key=(lambda x: str(x).lower()),
|
599
|
+
)
|
600
|
+
metrics_options = sorted(
|
601
|
+
list(
|
602
|
+
set(
|
603
|
+
keys_tuple[1] for keys_tuple in (_all_keys if _mk_alone else _keys)
|
604
|
+
).union(set(metric_keys or []))
|
605
|
+
),
|
606
|
+
key=(lambda x: str(x).lower()),
|
607
|
+
)
|
608
|
+
locations_options = sorted(
|
609
|
+
list(
|
610
|
+
set(
|
611
|
+
(
|
612
|
+
str(keys_tuple[2])
|
613
|
+
for keys_tuple in (_all_keys if _lk_alone else _keys)
|
614
|
+
)
|
615
|
+
).union(set((str(_lk) for _lk in (location_keys or []))))
|
616
|
+
),
|
617
|
+
key=(lambda x: str(x).lower()),
|
618
|
+
)
|
619
|
+
|
620
|
+
tags_options = sorted(
|
621
|
+
list(
|
622
|
+
set(
|
623
|
+
(_all_tags if _tags_alone else _tags_pipes)
|
624
|
+
).union(set(tags or []))
|
625
|
+
),
|
626
|
+
key=(lambda x: str(x).lower()),
|
627
|
+
)
|
629
628
|
|
630
|
-
_connectors_options.sort(key=lambda x: str(x).lower())
|
631
|
-
_metrics_options.sort(key=lambda x: str(x).lower())
|
632
|
-
_locations_options.sort(key=lambda x: str(x).lower())
|
633
|
-
_tags_options.sort(key=lambda x: str(x).lower())
|
634
|
-
connector_keys = [
|
635
|
-
ck
|
636
|
-
for ck in connector_keys
|
637
|
-
if ck in [
|
638
|
-
_ck['value']
|
639
|
-
for _ck in _connectors_options
|
640
|
-
]
|
641
|
-
]
|
642
|
-
metric_keys = [
|
643
|
-
mk
|
644
|
-
for mk in metric_keys
|
645
|
-
if mk in [
|
646
|
-
_mk['value']
|
647
|
-
for _mk in _metrics_options
|
648
|
-
]
|
649
|
-
]
|
650
|
-
location_keys = [
|
651
|
-
lk
|
652
|
-
for lk in location_keys
|
653
|
-
if lk in [
|
654
|
-
_lk['value']
|
655
|
-
for _lk in _locations_options
|
656
|
-
]
|
657
|
-
]
|
658
|
-
tags = [
|
659
|
-
tag
|
660
|
-
for tag in tags
|
661
|
-
if tag in [
|
662
|
-
_tag['value']
|
663
|
-
for _tag in _tags_options
|
664
|
-
]
|
665
|
-
]
|
666
629
|
return (
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
_locations_options,
|
672
|
-
location_keys,
|
673
|
-
_tags_options,
|
674
|
-
tags,
|
630
|
+
connectors_options,
|
631
|
+
metrics_options,
|
632
|
+
locations_options,
|
633
|
+
tags_options,
|
675
634
|
(instance_keys if update_instance_keys else dash.no_update),
|
676
635
|
instance_alerts,
|
677
636
|
)
|
678
637
|
|
638
|
+
|
639
|
+
@dash_app.callback(
|
640
|
+
Output('connector-keys-dropdown', 'value'),
|
641
|
+
Output('metric-keys-dropdown', 'value'),
|
642
|
+
Output('location-keys-dropdown', 'value'),
|
643
|
+
Output('tags-dropdown', 'value'),
|
644
|
+
Input('clear-all-keys-button', 'n_clicks'),
|
645
|
+
prevent_initial_call=True,
|
646
|
+
)
|
647
|
+
def clear_all_keys_button_click(n_clicks):
|
648
|
+
"""
|
649
|
+
Clear the keys dropdowns when the `Clear all` button is clicked.
|
650
|
+
"""
|
651
|
+
if not n_clicks:
|
652
|
+
raise PreventUpdate
|
653
|
+
|
654
|
+
return [], [], [], []
|
655
|
+
|
679
656
|
dash_app.clientside_callback(
|
680
657
|
"""
|
681
658
|
function(
|
@@ -5,28 +5,35 @@
|
|
5
5
|
Define callbacks for the `/dash/pipes/` page.
|
6
6
|
"""
|
7
7
|
|
8
|
-
from urllib.parse import parse_qs
|
8
|
+
from urllib.parse import parse_qs, quote_plus
|
9
|
+
from typing import List, Optional, Dict, Any
|
9
10
|
|
11
|
+
import dash
|
10
12
|
from dash.dependencies import Input, Output, State
|
11
13
|
from dash import no_update
|
12
14
|
from dash.exceptions import PreventUpdate
|
15
|
+
import dash_bootstrap_components as dbc
|
13
16
|
|
14
17
|
import meerschaum as mrsm
|
15
18
|
from meerschaum.api.dash import dash_app
|
16
|
-
from meerschaum.api.dash.components import
|
19
|
+
from meerschaum.api.dash.components import (
|
20
|
+
alert_from_success_tuple,
|
21
|
+
build_cards_grid,
|
22
|
+
)
|
17
23
|
from meerschaum.api.dash.pipes import (
|
18
24
|
build_pipe_card,
|
19
25
|
build_pipes_dropdown_keys_row,
|
20
26
|
build_pipes_tags_dropdown,
|
27
|
+
build_pipes_navbar,
|
21
28
|
)
|
22
29
|
from meerschaum.api import CHECK_UPDATE, get_api_connector
|
23
30
|
from meerschaum.utils.packages import import_html, import_dcc
|
24
31
|
from meerschaum.api.dash.sessions import is_session_authenticated
|
25
|
-
from meerschaum.utils.typing import Optional, Dict, Any
|
26
32
|
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
27
33
|
|
28
34
|
|
29
35
|
@dash_app.callback(
|
36
|
+
Output('pipes-navbar-div', 'children'),
|
30
37
|
Output('pipe-output-div', 'children'),
|
31
38
|
Input('pipes-location', 'pathname'),
|
32
39
|
State('pipes-location', 'search'),
|
@@ -38,7 +45,7 @@ def render_pipe_page_from_url(
|
|
38
45
|
session_data: Optional[Dict[str, Any]],
|
39
46
|
):
|
40
47
|
if not str(pathname).startswith('/dash/pipes'):
|
41
|
-
|
48
|
+
raise PreventUpdate
|
42
49
|
|
43
50
|
session_id = (session_data or {}).get('session-id', None)
|
44
51
|
authenticated = is_session_authenticated(str(session_id))
|
@@ -60,63 +67,103 @@ def render_pipe_page_from_url(
|
|
60
67
|
if isinstance(location_keys, str):
|
61
68
|
location_keys = location_keys.split(',')
|
62
69
|
|
70
|
+
keys = pathname.replace('/dash/pipes', '').lstrip('/').rstrip('/').split('/')
|
63
71
|
instance_connector = mrsm.get_connector(instance)
|
72
|
+
viewing_single_pipe = len(keys) in (2, 3)
|
64
73
|
if instance_connector is None:
|
65
|
-
return
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
if len(keys) not in (2, 3):
|
73
|
-
pipes = mrsm.get_pipes(
|
74
|
-
as_list=True,
|
75
|
-
connector_keys=connector_keys,
|
76
|
-
metric_keys=metric_keys,
|
77
|
-
location_keys=location_keys,
|
78
|
-
tags=tags,
|
79
|
-
instance=instance_connector,
|
74
|
+
return (
|
75
|
+
build_pipes_navbar(instance, with_instance_select=(not viewing_single_pipe)),
|
76
|
+
[
|
77
|
+
html.Br(),
|
78
|
+
alert_from_success_tuple((False, f"Invalid instance keys '{instance}'.")),
|
79
|
+
html.Br(),
|
80
|
+
]
|
80
81
|
)
|
82
|
+
|
83
|
+
if not viewing_single_pipe:
|
84
|
+
try:
|
85
|
+
pipes = mrsm.get_pipes(
|
86
|
+
as_list=True,
|
87
|
+
connector_keys=connector_keys,
|
88
|
+
metric_keys=metric_keys,
|
89
|
+
location_keys=location_keys,
|
90
|
+
tags=tags,
|
91
|
+
instance=instance_connector,
|
92
|
+
)
|
93
|
+
except Exception as e:
|
94
|
+
return (
|
95
|
+
build_pipes_navbar(instance, with_instance_select=False),
|
96
|
+
[
|
97
|
+
html.Br(),
|
98
|
+
alert_from_success_tuple(
|
99
|
+
(False, f"Failed to get pipes for instance '{instance}':\n{e}")
|
100
|
+
),
|
101
|
+
html.Br(),
|
102
|
+
dbc.Row(
|
103
|
+
[
|
104
|
+
dbc.Button(
|
105
|
+
"Reload",
|
106
|
+
id='pipes-reload-button',
|
107
|
+
size='lg',
|
108
|
+
href=(
|
109
|
+
"/dash/pipes"
|
110
|
+
if pathname.startswith('/dash/pipes/')
|
111
|
+
else "/dash/pipes/"
|
112
|
+
)
|
113
|
+
),
|
114
|
+
],
|
115
|
+
justify='center',
|
116
|
+
align='center',
|
117
|
+
className='h-50',
|
118
|
+
),
|
119
|
+
]
|
120
|
+
)
|
121
|
+
|
81
122
|
cards = [
|
82
123
|
build_pipe_card(pipe, authenticated=authenticated, include_manage=False)
|
83
124
|
for pipe in pipes
|
84
125
|
]
|
85
|
-
return
|
86
|
-
|
126
|
+
return (
|
127
|
+
build_pipes_navbar(instance, with_instance_select=True),
|
128
|
+
[
|
129
|
+
html.Div([
|
130
|
+
html.Br(),
|
131
|
+
build_pipes_dropdown_keys_row(
|
132
|
+
connector_keys,
|
133
|
+
metric_keys,
|
134
|
+
location_keys,
|
135
|
+
tags,
|
136
|
+
pipes,
|
137
|
+
instance_connector,
|
138
|
+
),
|
139
|
+
html.Br(),
|
140
|
+
build_pipes_tags_dropdown(
|
141
|
+
connector_keys,
|
142
|
+
metric_keys,
|
143
|
+
location_keys,
|
144
|
+
tags,
|
145
|
+
instance,
|
146
|
+
),
|
147
|
+
]),
|
87
148
|
html.Br(),
|
88
|
-
|
89
|
-
connector_keys,
|
90
|
-
metric_keys,
|
91
|
-
location_keys,
|
92
|
-
tags,
|
93
|
-
pipes,
|
94
|
-
instance_connector,
|
95
|
-
),
|
149
|
+
build_cards_grid(cards, 1),
|
96
150
|
html.Br(),
|
97
|
-
|
98
|
-
|
99
|
-
metric_keys,
|
100
|
-
location_keys,
|
101
|
-
tags,
|
102
|
-
instance,
|
103
|
-
),
|
104
|
-
]),
|
105
|
-
html.Br(),
|
106
|
-
build_cards_grid(cards, 1),
|
107
|
-
html.Br(),
|
108
|
-
]
|
151
|
+
]
|
152
|
+
)
|
109
153
|
|
110
154
|
ck = keys[0]
|
111
155
|
mk = keys[1]
|
112
156
|
lk = keys[2] if len(keys) == 3 else None
|
113
157
|
|
114
158
|
pipe = mrsm.Pipe(ck, mk, lk, instance=instance)
|
115
|
-
return
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
159
|
+
return (
|
160
|
+
build_pipes_navbar(instance, with_instance_select=False),
|
161
|
+
[
|
162
|
+
html.Br(),
|
163
|
+
build_pipe_card(pipe, authenticated=authenticated, include_manage=False),
|
164
|
+
html.Br(),
|
165
|
+
]
|
166
|
+
)
|
120
167
|
|
121
168
|
|
122
169
|
@dash_app.callback(
|
@@ -125,32 +172,64 @@ def render_pipe_page_from_url(
|
|
125
172
|
Input('pipes-metric-keys-dropdown', 'value'),
|
126
173
|
Input('pipes-location-keys-dropdown', 'value'),
|
127
174
|
Input('pipes-tags-dropdown', 'value'),
|
175
|
+
Input('instance-select', 'value'),
|
176
|
+
Input('pipes-clear-all-button', 'n_clicks'),
|
128
177
|
)
|
129
|
-
def update_location_on_pipes_filter_change(
|
178
|
+
def update_location_on_pipes_filter_change(
|
179
|
+
connector_keys: Optional[List[str]],
|
180
|
+
metric_keys: Optional[List[str]],
|
181
|
+
location_keys: Optional[List[str]],
|
182
|
+
tags: Optional[List[str]],
|
183
|
+
instance_keys: str,
|
184
|
+
clear_all_button_n_clicks: Optional[int],
|
185
|
+
):
|
130
186
|
"""
|
131
187
|
Update the URL parameters when clicking the dropdowns.
|
132
188
|
"""
|
133
|
-
|
189
|
+
ctx = dash.callback_context.triggered
|
190
|
+
if len(ctx) != 1:
|
191
|
+
raise PreventUpdate
|
192
|
+
|
193
|
+
if not any(
|
194
|
+
(connector_keys or [])
|
195
|
+
+ (metric_keys or [])
|
196
|
+
+ (location_keys or [])
|
197
|
+
+ (tags or [])
|
198
|
+
+ ([instance_keys] if instance_keys else [])
|
199
|
+
):
|
134
200
|
return ''
|
135
201
|
|
136
|
-
|
202
|
+
if ctx[0].get('prop_id', None) == 'pipes-clear-all-button.n_clicks':
|
203
|
+
connector_keys = []
|
204
|
+
metric_keys = []
|
205
|
+
location_keys = []
|
206
|
+
tags = []
|
207
|
+
|
208
|
+
include_instance_keys = instance_keys and instance_keys != str(get_api_connector())
|
209
|
+
search_str = ""
|
137
210
|
|
138
211
|
if connector_keys:
|
139
|
-
search_str += "connector_keys=" + ','.join(connector_keys)
|
140
|
-
if metric_keys or location_keys or tags:
|
212
|
+
search_str += "connector_keys=" + ','.join((quote_plus(ck) for ck in connector_keys))
|
213
|
+
if metric_keys or location_keys or tags or include_instance_keys:
|
141
214
|
search_str += '&'
|
142
215
|
|
143
216
|
if metric_keys:
|
144
|
-
search_str += "metric_keys=" + ','.join(metric_keys)
|
145
|
-
if location_keys or tags:
|
217
|
+
search_str += "metric_keys=" + ','.join((quote_plus(mk) for mk in metric_keys))
|
218
|
+
if location_keys or tags or include_instance_keys:
|
146
219
|
search_str += '&'
|
147
220
|
|
148
221
|
if location_keys:
|
149
|
-
search_str += "location_keys=" + ','.join(location_keys)
|
150
|
-
if tags:
|
222
|
+
search_str += "location_keys=" + ','.join((quote_plus(str(lk)) for lk in location_keys))
|
223
|
+
if tags or include_instance_keys:
|
151
224
|
search_str += '&'
|
152
225
|
|
153
226
|
if tags:
|
154
|
-
search_str += "tags=" + ','.join(tags)
|
227
|
+
search_str += "tags=" + ','.join((quote_plus(tag) for tag in tags))
|
228
|
+
if include_instance_keys:
|
229
|
+
search_str += '&'
|
230
|
+
|
231
|
+
if instance_keys:
|
232
|
+
if include_instance_keys:
|
233
|
+
search_str += "instance=" + quote_plus(instance_keys)
|
155
234
|
|
156
|
-
return search_str
|
235
|
+
return ('?' + search_str) if search_str else ''
|
@@ -54,7 +54,8 @@ def refresh_tokens_button_click(
|
|
54
54
|
html.H4('No tokens registered.'),
|
55
55
|
html.P('Click the `+` button to register a new token.'),
|
56
56
|
],
|
57
|
-
|
57
|
+
build_tokens_register_input_modal(),
|
58
|
+
alerts,
|
58
59
|
)
|
59
60
|
|
60
61
|
return tokens_table, build_tokens_register_input_modal(), alerts
|
@@ -13,7 +13,7 @@ from meerschaum.utils.typing import SuccessTuple, List
|
|
13
13
|
from meerschaum._internal.static import STATIC_CONFIG
|
14
14
|
from meerschaum.utils.misc import remove_ansi
|
15
15
|
from meerschaum._internal.shell.Shell import get_shell_intro
|
16
|
-
from meerschaum.api import endpoints, CHECK_UPDATE, docs_enabled
|
16
|
+
from meerschaum.api import endpoints, CHECK_UPDATE, docs_enabled, get_api_connector
|
17
17
|
from meerschaum.connectors import instance_types, _load_builtin_custom_connectors
|
18
18
|
from meerschaum.utils.misc import get_connector_labels
|
19
19
|
from meerschaum.config import __doc__ as doc
|
@@ -104,7 +104,7 @@ instance_select = dbc.Select(
|
|
104
104
|
id='instance-select',
|
105
105
|
size='sm',
|
106
106
|
options=[
|
107
|
-
{'label': i, 'value': i}
|
107
|
+
{'label': (i[:32] + '…') if len(i) > 32 else i, 'value': i}
|
108
108
|
for i in get_connector_labels(*instance_types)
|
109
109
|
],
|
110
110
|
class_name='dbc_dark custom-select custom-select-sm',
|
@@ -163,6 +163,7 @@ pages_navbar = html.Div(
|
|
163
163
|
id='pages-navbar-div',
|
164
164
|
)
|
165
165
|
|
166
|
+
|
166
167
|
navbar = dbc.Navbar(
|
167
168
|
dbc.Container(
|
168
169
|
[
|
@@ -171,13 +172,11 @@ navbar = dbc.Navbar(
|
|
171
172
|
dbc.Collapse(
|
172
173
|
dbc.Row(
|
173
174
|
[
|
174
|
-
dbc.Col(instance_select),
|
175
|
-
dbc.Col(
|
176
|
-
sign_out_button,
|
177
|
-
className="ms-auto",
|
178
|
-
),
|
175
|
+
dbc.Col(instance_select, width="auto"),
|
176
|
+
dbc.Col(sign_out_button, width="auto"),
|
179
177
|
],
|
180
178
|
className="g-0 ms-auto flex-nowrap mt-3 mt-md-0",
|
179
|
+
align="center",
|
181
180
|
),
|
182
181
|
id='navbar-collapse',
|
183
182
|
is_open=False,
|
meerschaum/api/dash/keys.py
CHANGED
@@ -227,7 +227,23 @@ dropdown_tab_content = html.Div([
|
|
227
227
|
[
|
228
228
|
dropdown_keys_row,
|
229
229
|
html.Br(),
|
230
|
-
|
230
|
+
dbc.Row(
|
231
|
+
[
|
232
|
+
dbc.Col(tags_dropdown, width=True),
|
233
|
+
dbc.Col(
|
234
|
+
dbc.Button(
|
235
|
+
"Clear all",
|
236
|
+
id='clear-all-keys-button',
|
237
|
+
color='link',
|
238
|
+
size='sm',
|
239
|
+
style={'text-decoration': 'none'},
|
240
|
+
),
|
241
|
+
width='auto',
|
242
|
+
),
|
243
|
+
],
|
244
|
+
className='g-0',
|
245
|
+
align='center',
|
246
|
+
),
|
231
247
|
], ### end of card children
|
232
248
|
className='card-text',
|
233
249
|
)
|
@@ -7,17 +7,27 @@ Display pipes via a shareable URL.
|
|
7
7
|
|
8
8
|
from meerschaum.api import CHECK_UPDATE
|
9
9
|
from meerschaum.utils.packages import import_html, import_dcc
|
10
|
-
from meerschaum.api.dash.components import
|
10
|
+
from meerschaum.api.dash.components import (
|
11
|
+
download_dataframe,
|
12
|
+
)
|
11
13
|
|
12
14
|
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
13
15
|
import dash_bootstrap_components as dbc
|
14
16
|
|
15
|
-
|
16
17
|
layout = [
|
17
|
-
|
18
|
+
html.Div(id='pipes-navbar-div'),
|
18
19
|
dcc.Location('pipes-location'),
|
19
20
|
download_dataframe,
|
20
21
|
dbc.Container([
|
21
|
-
|
22
|
+
dcc.Loading(
|
23
|
+
html.Div(id='pipe-output-div'),
|
24
|
+
id='pipes-loading',
|
25
|
+
type='circle',
|
26
|
+
delay_hide=1000,
|
27
|
+
delay_show=1000,
|
28
|
+
style={
|
29
|
+
'padding-top': '100px',
|
30
|
+
},
|
31
|
+
),
|
22
32
|
])
|
23
33
|
]
|
meerschaum/api/dash/pipes.py
CHANGED
@@ -14,17 +14,24 @@ from urllib.parse import urlencode
|
|
14
14
|
|
15
15
|
from meerschaum.utils import fetch_pipes_keys
|
16
16
|
from meerschaum.utils.typing import List, Optional, Dict, Any, Tuple, Union
|
17
|
-
from meerschaum.utils.misc import
|
17
|
+
from meerschaum.utils.misc import get_connector_labels
|
18
|
+
from meerschaum.connectors import instance_types
|
18
19
|
from meerschaum.utils.packages import attempt_import, import_dcc, import_html, import_pandas
|
19
20
|
from meerschaum.utils.sql import get_pd_type
|
20
21
|
from meerschaum.utils.yaml import yaml
|
21
22
|
from meerschaum.utils.warnings import warn
|
22
23
|
from meerschaum.utils.dataframe import to_json, to_simple_lines
|
23
24
|
from meerschaum.connectors.sql._fetch import get_pipe_query
|
24
|
-
from meerschaum.api import CHECK_UPDATE
|
25
|
+
from meerschaum.api import CHECK_UPDATE, get_api_connector
|
25
26
|
from meerschaum.api.dash import debug, _get_pipes
|
26
27
|
from meerschaum.api.dash.connectors import get_web_connector
|
27
|
-
from meerschaum.api.dash.components import
|
28
|
+
from meerschaum.api.dash.components import (
|
29
|
+
alert_from_success_tuple,
|
30
|
+
build_cards_grid,
|
31
|
+
sign_out_button,
|
32
|
+
logo_row,
|
33
|
+
pages_offcanvas,
|
34
|
+
)
|
28
35
|
from meerschaum.api.dash.sessions import is_session_authenticated
|
29
36
|
from meerschaum.config import get_config
|
30
37
|
import meerschaum as mrsm
|
@@ -835,6 +842,28 @@ def build_pipes_dropdown_keys_row(
|
|
835
842
|
mk_alone = metric_keys and not any([str(x) for x in (connector_keys + tags + location_keys)])
|
836
843
|
lk_alone = location_keys and not any([str(x) for x in (connector_keys + metric_keys + tags)])
|
837
844
|
all_keys = fetch_pipes_keys('registered', instance_connector)
|
845
|
+
|
846
|
+
ck_options_source = (
|
847
|
+
{keys_tuple[0] for keys_tuple in all_keys}
|
848
|
+
if ck_alone
|
849
|
+
else {p.connector_keys for p in pipes}
|
850
|
+
)
|
851
|
+
ck_options = sorted(ck_options_source.union(connector_keys))
|
852
|
+
|
853
|
+
mk_options_source = (
|
854
|
+
{keys_tuple[1] for keys_tuple in all_keys}
|
855
|
+
if mk_alone
|
856
|
+
else {p.metric_key for p in pipes}
|
857
|
+
)
|
858
|
+
mk_options = sorted(mk_options_source.union(metric_keys))
|
859
|
+
|
860
|
+
lk_options_source = (
|
861
|
+
{str(keys_tuple[2]) for keys_tuple in all_keys}
|
862
|
+
if lk_alone
|
863
|
+
else {str(p.location_key) for p in pipes}
|
864
|
+
)
|
865
|
+
lk_options = sorted(lk_options_source.union({str(lk) for lk in location_keys}))
|
866
|
+
|
838
867
|
return dbc.Row(
|
839
868
|
[
|
840
869
|
dbc.Col(
|
@@ -842,11 +871,7 @@ def build_pipes_dropdown_keys_row(
|
|
842
871
|
[
|
843
872
|
dcc.Dropdown(
|
844
873
|
id='pipes-connector-keys-dropdown',
|
845
|
-
options=
|
846
|
-
sorted(list({pipe.connector_keys for pipe in pipes}))
|
847
|
-
if not ck_alone
|
848
|
-
else sorted(list({ck for ck, _, _ in all_keys}))
|
849
|
-
),
|
874
|
+
options=ck_options,
|
850
875
|
value=[str(ck) for ck in connector_keys],
|
851
876
|
placeholder='Connectors',
|
852
877
|
multi=True,
|
@@ -863,11 +888,7 @@ def build_pipes_dropdown_keys_row(
|
|
863
888
|
[
|
864
889
|
dcc.Dropdown(
|
865
890
|
id='pipes-metric-keys-dropdown',
|
866
|
-
options=
|
867
|
-
sorted(list({pipe.metric_key for pipe in pipes}))
|
868
|
-
if not mk_alone
|
869
|
-
else sorted(list({mk for _, mk, _ in all_keys}))
|
870
|
-
),
|
891
|
+
options=mk_options,
|
871
892
|
value=[str(mk) for mk in metric_keys],
|
872
893
|
placeholder='Metrics',
|
873
894
|
multi=True,
|
@@ -884,11 +905,7 @@ def build_pipes_dropdown_keys_row(
|
|
884
905
|
[
|
885
906
|
dcc.Dropdown(
|
886
907
|
id='pipes-location-keys-dropdown',
|
887
|
-
options=
|
888
|
-
sorted(list({str(pipe.location_key) for pipe in pipes}))
|
889
|
-
if not lk_alone
|
890
|
-
else sorted(list({str(lk) for _, _, lk in all_keys}))
|
891
|
-
),
|
908
|
+
options=lk_options,
|
892
909
|
value=[str(lk) for lk in location_keys],
|
893
910
|
placeholder='Locations',
|
894
911
|
multi=True,
|
@@ -910,7 +927,7 @@ def build_pipes_tags_dropdown(
|
|
910
927
|
location_keys: List[str],
|
911
928
|
tags: List[str],
|
912
929
|
instance: str,
|
913
|
-
) ->
|
930
|
+
) -> dbc.Row:
|
914
931
|
"""
|
915
932
|
Build the tags dropdown for the dedicated pipes page.
|
916
933
|
"""
|
@@ -935,16 +952,84 @@ def build_pipes_tags_dropdown(
|
|
935
952
|
str(tag)
|
936
953
|
for tag in (_all_tags if _tags_alone else _tags_pipes)
|
937
954
|
]
|
955
|
+
if tags:
|
956
|
+
tags_options += [tag for tag in tags if tag not in tags_options]
|
938
957
|
|
958
|
+
return dbc.Row(
|
959
|
+
[
|
960
|
+
dbc.Col(
|
961
|
+
html.Div(
|
962
|
+
dcc.Dropdown(
|
963
|
+
id='pipes-tags-dropdown',
|
964
|
+
options=tags_options,
|
965
|
+
value=tags,
|
966
|
+
placeholder='Tags',
|
967
|
+
multi=True,
|
968
|
+
searchable=True,
|
969
|
+
),
|
970
|
+
className="dbc_dark",
|
971
|
+
id="pipes-tags-dropdown-div",
|
972
|
+
),
|
973
|
+
width=True,
|
974
|
+
),
|
975
|
+
dbc.Col(
|
976
|
+
dbc.Button(
|
977
|
+
"Clear all",
|
978
|
+
color='link',
|
979
|
+
size='sm',
|
980
|
+
style={'text-decoration': 'none'},
|
981
|
+
id='pipes-clear-all-button',
|
982
|
+
),
|
983
|
+
width='auto',
|
984
|
+
),
|
985
|
+
],
|
986
|
+
className='g-0',
|
987
|
+
align='center',
|
988
|
+
)
|
989
|
+
|
990
|
+
|
991
|
+
def build_pipes_navbar(instance_keys: Optional[str] = None, with_instance_select: bool = True):
|
992
|
+
"""
|
993
|
+
Build the navbar from the selected instance keys.
|
994
|
+
"""
|
995
|
+
instance_select = dbc.Select(
|
996
|
+
id='instance-select',
|
997
|
+
size='sm',
|
998
|
+
value=instance_keys or str(get_api_connector()),
|
999
|
+
options=[
|
1000
|
+
{'label': (i[:32] + '…') if len(i) > 32 else i, 'value': i}
|
1001
|
+
for i in get_connector_labels(*instance_types)
|
1002
|
+
],
|
1003
|
+
class_name='dbc_dark custom-select custom-select-sm',
|
1004
|
+
)
|
1005
|
+
instance_select_div_style = {} if with_instance_select else {'visibility': 'hidden'}
|
1006
|
+
instance_select_div = html.Div(instance_select, style=instance_select_div_style)
|
939
1007
|
return html.Div(
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
1008
|
+
[
|
1009
|
+
pages_offcanvas,
|
1010
|
+
dbc.Navbar(
|
1011
|
+
dbc.Container(
|
1012
|
+
[
|
1013
|
+
logo_row,
|
1014
|
+
dbc.NavbarToggler(id="navbar-toggler", n_clicks=0),
|
1015
|
+
dbc.Collapse(
|
1016
|
+
dbc.Row(
|
1017
|
+
[
|
1018
|
+
dbc.Col(instance_select_div, width='auto'),
|
1019
|
+
dbc.Col(sign_out_button, width='auto'),
|
1020
|
+
],
|
1021
|
+
className="g-0 ms-auto flex-nowrap mt-3 mt-md-0",
|
1022
|
+
align='center',
|
1023
|
+
),
|
1024
|
+
id='navbar-collapse',
|
1025
|
+
is_open=False,
|
1026
|
+
navbar=True,
|
1027
|
+
),
|
1028
|
+
]
|
1029
|
+
),
|
1030
|
+
dark=True,
|
1031
|
+
color='dark'
|
1032
|
+
),
|
1033
|
+
],
|
1034
|
+
id='pages-navbar-div',
|
950
1035
|
)
|
meerschaum/api/dash/tokens.py
CHANGED
@@ -65,7 +65,7 @@ def get_tokens_table(session_id: Optional[str] = None) -> Tuple[dbc.Table, List[
|
|
65
65
|
html.Td("✅" if token.is_valid else "❌"),
|
66
66
|
html.Td([
|
67
67
|
dbc.Button(
|
68
|
-
html.B("
|
68
|
+
html.B("⋮"),
|
69
69
|
color='link',
|
70
70
|
size='sm',
|
71
71
|
id={'type': 'tokens-context-button', 'index': str(token.id)},
|
meerschaum/config/_version.py
CHANGED
@@ -147,7 +147,9 @@ def fetch_pipes_keys(
|
|
147
147
|
tags: Optional[List[str]] = None,
|
148
148
|
params: Optional[Dict[str, Any]] = None,
|
149
149
|
debug: bool = False
|
150
|
-
) -> List[
|
150
|
+
) -> List[
|
151
|
+
Tuple[str, str, Union[str, None], Dict[str, Any]]
|
152
|
+
]:
|
151
153
|
"""
|
152
154
|
Return a list of tuples corresponding to the parameters provided.
|
153
155
|
|
@@ -174,7 +176,7 @@ def fetch_pipes_keys(
|
|
174
176
|
|
175
177
|
Returns
|
176
178
|
-------
|
177
|
-
A list of tuples of pipes' keys (connector_keys, metric_key, location_key).
|
179
|
+
A list of tuples of pipes' keys and parameters (connector_keys, metric_key, location_key, parameters).
|
178
180
|
"""
|
179
181
|
from meerschaum.utils.packages import attempt_import
|
180
182
|
from meerschaum.utils.misc import separate_negation_values
|
@@ -254,6 +256,11 @@ def fetch_pipes_keys(
|
|
254
256
|
pipes_tbl.c.connector_keys,
|
255
257
|
pipes_tbl.c.metric_key,
|
256
258
|
pipes_tbl.c.location_key,
|
259
|
+
(
|
260
|
+
pipes_tbl.c.parameters['tags']
|
261
|
+
if self.flavor in json_flavors
|
262
|
+
else pipes_tbl.c.parameters
|
263
|
+
),
|
257
264
|
]
|
258
265
|
)
|
259
266
|
|
@@ -276,7 +283,6 @@ def fetch_pipes_keys(
|
|
276
283
|
if _in_tags:
|
277
284
|
ors.append(
|
278
285
|
sqlalchemy.and_(
|
279
|
-
pipes_tbl.c['parameters'].cast(postgresql.JSONB).has_key('tags'),
|
280
286
|
pipes_tbl.c['parameters']['tags'].cast(
|
281
287
|
postgresql.JSONB
|
282
288
|
).contains(_in_tags)
|
@@ -286,7 +292,6 @@ def fetch_pipes_keys(
|
|
286
292
|
nands.append(
|
287
293
|
sqlalchemy.not_(
|
288
294
|
sqlalchemy.and_(
|
289
|
-
pipes_tbl.c['parameters'].cast(postgresql.JSONB).has_key('tags'),
|
290
295
|
pipes_tbl.c['parameters']['tags'].cast(
|
291
296
|
postgresql.JSONB
|
292
297
|
).contains([xt])
|
@@ -340,7 +345,7 @@ def fetch_pipes_keys(
|
|
340
345
|
except Exception as e:
|
341
346
|
error(str(e))
|
342
347
|
|
343
|
-
return
|
348
|
+
return rows
|
344
349
|
|
345
350
|
|
346
351
|
def create_pipe_indices(
|
@@ -24,6 +24,7 @@ _skip_index_names_flavors = {'mssql',}
|
|
24
24
|
def get_tables(
|
25
25
|
mrsm_instance: Optional[Union[str, InstanceConnector]] = None,
|
26
26
|
create: Optional[bool] = None,
|
27
|
+
refresh: bool = False,
|
27
28
|
debug: bool = False,
|
28
29
|
) -> Union[Dict[str, 'sqlalchemy.Table'], bool]:
|
29
30
|
"""
|
@@ -37,6 +38,9 @@ def get_tables(
|
|
37
38
|
create: Optional[bool], default None
|
38
39
|
If `True`, create the tables if they don't exist.
|
39
40
|
|
41
|
+
refresh: bool, default False
|
42
|
+
If `True`, invalidate and rebuild any cache.
|
43
|
+
|
40
44
|
debug: bool, default False
|
41
45
|
Verbosity Toggle.
|
42
46
|
|
@@ -67,7 +71,15 @@ def get_tables(
|
|
67
71
|
else: ### NOTE: mrsm_instance MUST BE a SQL Connector for this to work!
|
68
72
|
conn = mrsm_instance
|
69
73
|
|
70
|
-
cache_expired =
|
74
|
+
cache_expired = refresh or (
|
75
|
+
(
|
76
|
+
_check_create_cache(conn, debug=debug)
|
77
|
+
if conn.flavor != 'sqlite'
|
78
|
+
else True
|
79
|
+
)
|
80
|
+
if conn.type == 'sql'
|
81
|
+
else False
|
82
|
+
)
|
71
83
|
create = create or cache_expired
|
72
84
|
|
73
85
|
### Skip if the connector is not a SQL connector.
|
@@ -75,6 +87,10 @@ def get_tables(
|
|
75
87
|
return {}
|
76
88
|
|
77
89
|
conn_key = str(conn)
|
90
|
+
|
91
|
+
if refresh:
|
92
|
+
_ = connector_tables.pop(conn_key, None)
|
93
|
+
|
78
94
|
if conn_key in connector_tables:
|
79
95
|
return connector_tables[conn_key]
|
80
96
|
|
@@ -248,8 +264,9 @@ def get_tables(
|
|
248
264
|
|
249
265
|
_write_create_cache(mrsm.get_connector(str(mrsm_instance)), debug=debug)
|
250
266
|
|
251
|
-
|
252
|
-
|
267
|
+
if conn.flavor != 'sqlite':
|
268
|
+
with open(pickle_path, 'wb') as f:
|
269
|
+
pickle.dump(conn.metadata, f)
|
253
270
|
|
254
271
|
connector_tables[conn_key] = _tables
|
255
272
|
return connector_tables[conn_key]
|
meerschaum/core/Pipe/__init__.py
CHANGED
@@ -562,7 +562,7 @@ class Pipe:
|
|
562
562
|
'connector_keys': self.connector_keys,
|
563
563
|
'metric_key': self.metric_key,
|
564
564
|
'location_key': self.location_key,
|
565
|
-
'parameters': self.parameters,
|
565
|
+
'parameters': self._attributes.get('parameters', None),
|
566
566
|
'instance_keys': self.instance_keys,
|
567
567
|
}
|
568
568
|
|
@@ -598,3 +598,19 @@ class Pipe:
|
|
598
598
|
if aliased_key is not None:
|
599
599
|
key = aliased_key
|
600
600
|
return getattr(self, key, None)
|
601
|
+
|
602
|
+
def __copy__(self):
|
603
|
+
"""
|
604
|
+
Return a shallow copy of the current pipe.
|
605
|
+
"""
|
606
|
+
return mrsm.Pipe(
|
607
|
+
self.connector_keys, self.metric_key, self.location_key,
|
608
|
+
instance=self.instance_keys,
|
609
|
+
parameters=self._attributes.get('parameters', None),
|
610
|
+
)
|
611
|
+
|
612
|
+
def __deepcopy__(self, memo):
|
613
|
+
"""
|
614
|
+
Return a deep copy of the current pipe.
|
615
|
+
"""
|
616
|
+
return self.__copy__()
|
meerschaum/utils/_get_pipes.py
CHANGED
@@ -128,11 +128,12 @@ def get_pipes(
|
|
128
128
|
```
|
129
129
|
"""
|
130
130
|
|
131
|
+
import json
|
132
|
+
from collections import defaultdict
|
131
133
|
from meerschaum.config import get_config
|
132
134
|
from meerschaum.utils.warnings import error
|
133
135
|
from meerschaum.utils.misc import filter_keywords
|
134
136
|
from meerschaum.utils.pool import get_pool
|
135
|
-
from collections import defaultdict
|
136
137
|
|
137
138
|
if connector_keys is None:
|
138
139
|
connector_keys = []
|
@@ -194,19 +195,42 @@ def get_pipes(
|
|
194
195
|
### obtained from the chosen `method`.
|
195
196
|
from meerschaum import Pipe
|
196
197
|
pipes = {}
|
197
|
-
for
|
198
|
+
for keys_tuple in result:
|
199
|
+
ck, mk, lk = keys_tuple[0], keys_tuple[1], keys_tuple[2]
|
200
|
+
pipe_tags_or_parameters = keys_tuple[3] if len(keys_tuple) == 4 else None
|
201
|
+
pipe_parameters = (
|
202
|
+
pipe_tags_or_parameters
|
203
|
+
if isinstance(pipe_tags_or_parameters, (dict, str))
|
204
|
+
else None
|
205
|
+
)
|
206
|
+
if isinstance(pipe_parameters, str):
|
207
|
+
pipe_parameters = json.loads(pipe_parameters)
|
208
|
+
pipe_tags = (
|
209
|
+
pipe_tags_or_parameters
|
210
|
+
if isinstance(pipe_tags_or_parameters, list)
|
211
|
+
else (
|
212
|
+
pipe_tags_or_parameters.get('tags', None)
|
213
|
+
if isinstance(pipe_tags_or_parameters, dict)
|
214
|
+
else None
|
215
|
+
)
|
216
|
+
)
|
217
|
+
|
198
218
|
if ck not in pipes:
|
199
219
|
pipes[ck] = {}
|
200
220
|
|
201
221
|
if mk not in pipes[ck]:
|
202
222
|
pipes[ck][mk] = {}
|
203
223
|
|
204
|
-
|
224
|
+
pipe = Pipe(
|
205
225
|
ck, mk, lk,
|
206
226
|
mrsm_instance = connector,
|
227
|
+
parameters = pipe_parameters,
|
228
|
+
tags = pipe_tags,
|
207
229
|
debug = debug,
|
208
230
|
**filter_keywords(Pipe, **kw)
|
209
231
|
)
|
232
|
+
pipe.__dict__['_tags'] = pipe_tags
|
233
|
+
pipes[ck][mk][lk] = pipe
|
210
234
|
|
211
235
|
if not as_list and not as_tags_dict:
|
212
236
|
return pipes
|
@@ -218,7 +242,9 @@ def get_pipes(
|
|
218
242
|
|
219
243
|
pool = get_pool(workers=(workers if connector.IS_THREAD_SAFE else 1))
|
220
244
|
def gather_pipe_tags(pipe: mrsm.Pipe) -> Tuple[mrsm.Pipe, List[str]]:
|
221
|
-
|
245
|
+
_tags = pipe.__dict__.get('_tags', None)
|
246
|
+
gathered_tags = _tags if _tags is not None else pipe.tags
|
247
|
+
return pipe, (gathered_tags or [])
|
222
248
|
|
223
249
|
tags_pipes = defaultdict(lambda: [])
|
224
250
|
pipes_tags = dict(pool.map(gather_pipe_tags, pipes_list))
|
meerschaum/utils/pipes.py
CHANGED
@@ -165,10 +165,14 @@ def replace_pipes_in_dict(
|
|
165
165
|
A dictionary where every pipe is replaced with the output of a function.
|
166
166
|
|
167
167
|
"""
|
168
|
-
def change_dict(d
|
168
|
+
def change_dict(d: Dict[Any, Any]) -> None:
|
169
169
|
for k, v in d.items():
|
170
170
|
if isinstance(v, dict):
|
171
171
|
change_dict(v, func)
|
172
|
+
elif isinstance(v, list):
|
173
|
+
d[k] = [func(i) for i in v]
|
174
|
+
elif isinstance(v, tuple):
|
175
|
+
d[k] = tuple([func(i) for i in v])
|
172
176
|
else:
|
173
177
|
d[k] = func(v)
|
174
178
|
|
@@ -177,5 +181,5 @@ def replace_pipes_in_dict(
|
|
177
181
|
pipes = get_pipes(debug=debug, **kw)
|
178
182
|
|
179
183
|
result = copy.deepcopy(pipes)
|
180
|
-
change_dict(result
|
184
|
+
change_dict(result)
|
181
185
|
return result
|
@@ -51,22 +51,22 @@ meerschaum/actions/verify.py,sha256=yKNqh2T38t3yxqErr2o8i-nNG4ZZuyQUkaImATRdl5M,
|
|
51
51
|
meerschaum/api/__init__.py,sha256=dRoIuyjkx6I8-LgLa0RbxwJCaAfSiGbgtf8fTbS7-Rw,10756
|
52
52
|
meerschaum/api/_chain.py,sha256=h8-WXUGXX6AqzdALfsBC5uv0FkAcLdHJXCGzqzuq89k,875
|
53
53
|
meerschaum/api/_chunks.py,sha256=rmhz8h4MZDnjkE02fDqDEwbYwwZbnU4gVwy3-QqB5y0,1898
|
54
|
-
meerschaum/api/_events.py,sha256=
|
54
|
+
meerschaum/api/_events.py,sha256=LPLXIurprtpWsgjIsDLMOPVT9rZjavkZzKh4dU6CQCE,3804
|
55
55
|
meerschaum/api/_exceptions.py,sha256=xfbWp8F8JYrMUdtDXesn8C8e39_jAXHz51IosIGjkVM,463
|
56
56
|
meerschaum/api/_oauth2.py,sha256=MLwOb-ZnJeBfn3OexdRhcboU39RBMnRt15s5e2d-lUs,5429
|
57
57
|
meerschaum/api/_tokens.py,sha256=t9K0TFzyJ4dOg04_QKOWCINO66rSJkH2Ct03lyXIjEs,3070
|
58
58
|
meerschaum/api/_websockets.py,sha256=EMT9wB3yELu_WyCMqn9ZpgMDh23spUUchouRLCCLVuw,1509
|
59
59
|
meerschaum/api/dash/__init__.py,sha256=-RpTps4ntFNlgSW0mW50ZHAgUd5tN1Ua3F5I3XsLY_0,1914
|
60
|
-
meerschaum/api/dash/components.py,sha256=
|
60
|
+
meerschaum/api/dash/components.py,sha256=PMMLCcRHd0ADa8DjeH1xB2NXnIyl92HKW4LOCtmq55Y,10782
|
61
61
|
meerschaum/api/dash/connectors.py,sha256=-Wd40ieYJI2nOASXi4V1C4bvLekjnN_tj6zp7HgZDl0,791
|
62
62
|
meerschaum/api/dash/graphs.py,sha256=wJUDWzcLN8-C3xko6rj0F2v7Rt8YDkSXoVkkXJjYGIk,2046
|
63
63
|
meerschaum/api/dash/jobs.py,sha256=p0mC30jO7aYS0vUbfn540d66-s19_c-GgjyfNmVXgrs,7682
|
64
|
-
meerschaum/api/dash/keys.py,sha256=
|
65
|
-
meerschaum/api/dash/pipes.py,sha256=
|
64
|
+
meerschaum/api/dash/keys.py,sha256=pGIbKxp5RsIelzAU4WZMcYGDN835tF4mGhoktydc42M,8561
|
65
|
+
meerschaum/api/dash/pipes.py,sha256=C6w8GmQvZcBWZE--Kc9xVLyljkU8Uyl-NiQSrlRLY9g,36391
|
66
66
|
meerschaum/api/dash/plugins.py,sha256=KdfG04f6SsUpBg-nm7MUJegFGuElOj-GAkxDX98hi60,3768
|
67
67
|
meerschaum/api/dash/sessions.py,sha256=jUM0a9CXNZC3j7SF3QkZim-8ZAbDom-V1iXklvMyBZE,5382
|
68
68
|
meerschaum/api/dash/sync.py,sha256=9lt7IRdG-fe9gf_ZO_viPiGlerX7ic6r_VFocv3I51A,504
|
69
|
-
meerschaum/api/dash/tokens.py,sha256=
|
69
|
+
meerschaum/api/dash/tokens.py,sha256=7_4k45drB6uoL1izDFo6TezzSQ6v1DP_aHw7orYk4ZU,20832
|
70
70
|
meerschaum/api/dash/users.py,sha256=3wq3ZG51DxOjNeF-X5HdlXD1MYQ1nQ9oowYSvFEY7hs,1050
|
71
71
|
meerschaum/api/dash/websockets.py,sha256=L6e7Ved7Osh9JRJitS4wMbVGPrrXPD4uB61Yj1Y5aug,927
|
72
72
|
meerschaum/api/dash/webterm.py,sha256=Z7P99RzRQnB11LRWupwFpzyyZxouNbpFpXk0nYSGvwI,4503
|
@@ -78,13 +78,13 @@ meerschaum/api/dash/assets/logo_48x48.png,sha256=hTR5BHUHEN4yP2xiqAcDciuigoII9T3
|
|
78
78
|
meerschaum/api/dash/assets/logo_500x500.png,sha256=9EUtf6wQcEZTXHKfQ2kjNXod6Rn_4DTB_BkTgxggq00,67702
|
79
79
|
meerschaum/api/dash/callbacks/__init__.py,sha256=flHWiTSjrdgVNLgFutSnaqYogVUgnqRFWy3K0-n0wFo,651
|
80
80
|
meerschaum/api/dash/callbacks/custom.py,sha256=8nUCZ-AhCTJ079r8eZ6nBE3bVZlkrvvC-bwP0U9zuv8,1791
|
81
|
-
meerschaum/api/dash/callbacks/dashboard.py,sha256=
|
81
|
+
meerschaum/api/dash/callbacks/dashboard.py,sha256=ghm_B6n0BtEbH8dL2xEbYKCnYjGf0_Iy50eNVXHSzZw,38057
|
82
82
|
meerschaum/api/dash/callbacks/jobs.py,sha256=9MlHePZJ8sGSC2Sfo9BKyTix4-_7AP69njuM8k5Wmus,8749
|
83
83
|
meerschaum/api/dash/callbacks/login.py,sha256=mEvMgV-f85H6DvqNdTvJPoiwHqTnhWY2nf_zLB26ipE,2876
|
84
|
-
meerschaum/api/dash/callbacks/pipes.py,sha256=
|
84
|
+
meerschaum/api/dash/callbacks/pipes.py,sha256=mK9d2A789fsMkT8BF6FIrxWpzPDzfa9VgAgeTZv05G8,7801
|
85
85
|
meerschaum/api/dash/callbacks/plugins.py,sha256=GhhA8GZBCNcz65pBE8hn8BNBEiHjXfcTiqvBNeox4XQ,2759
|
86
86
|
meerschaum/api/dash/callbacks/register.py,sha256=FFl5-PDILOfm-Vu1uouzSLYIncDLFgC4fDirsE16q54,3669
|
87
|
-
meerschaum/api/dash/callbacks/tokens.py,sha256=
|
87
|
+
meerschaum/api/dash/callbacks/tokens.py,sha256=zkmqDenGjCrzQjNA5HyTOjcKDk2wYG4qE3xhjRDlTaE,11723
|
88
88
|
meerschaum/api/dash/callbacks/settings/__init__.py,sha256=pttbJMJGfd5I_oCWfbpbbVtXZp7pyerl9ESgY9xwUwI,157
|
89
89
|
meerschaum/api/dash/callbacks/settings/password_reset.py,sha256=GLvp5yTcmH6BFPCnj-P7nbMivKVK7yRFSubq2mAEUSI,2500
|
90
90
|
meerschaum/api/dash/pages/__init__.py,sha256=rMrk5U8vDQTNg4mIhBfVldcq0r6wCZUOvSrS3eUFrEE,432
|
@@ -92,7 +92,7 @@ meerschaum/api/dash/pages/dashboard.py,sha256=fviwgh8QaKU1rKPrO4Pjk-Eya2xhKVC2rd
|
|
92
92
|
meerschaum/api/dash/pages/error.py,sha256=-uCrASuIBrceHcc-leLeEoLos2ibSBWG0XMFQzFwtbw,595
|
93
93
|
meerschaum/api/dash/pages/jobs.py,sha256=lKUE5iiKG37bOEGDpQ5JRWysMwn-_SRhZOHoj8e_q-c,605
|
94
94
|
meerschaum/api/dash/pages/login.py,sha256=Qjc-kDL9wW4D1cN48x0MrmWCME4igHDt0VkX9JSipjY,4603
|
95
|
-
meerschaum/api/dash/pages/pipes.py,sha256=
|
95
|
+
meerschaum/api/dash/pages/pipes.py,sha256=Dqxh76XWjHqjSNfQ99mFtX39Xi6fmVlNQRX0uy0_9-8,796
|
96
96
|
meerschaum/api/dash/pages/plugins.py,sha256=EX-M99bxvRSrI-9bIBocj-tmBpf6NgPQ813sJ_HSXS8,1731
|
97
97
|
meerschaum/api/dash/pages/register.py,sha256=dqhsiu2OhrXhs4RL41_CpqipdrWo1-_roASvZIDBAq8,2364
|
98
98
|
meerschaum/api/dash/pages/tokens.py,sha256=cqscrKcU1ODO8mo2xBeevQnNhSUZYjgU3o7QNMZ7Cik,1332
|
@@ -150,7 +150,7 @@ meerschaum/config/_preprocess.py,sha256=-AEA8m_--KivZwTQ1sWN6LTn5sio_fUr2XZ51BO6
|
|
150
150
|
meerschaum/config/_read_config.py,sha256=BVGZbaS_bFcLb6fQNbwXIAS2sjLVg5wfuLs1ghVtK9g,15798
|
151
151
|
meerschaum/config/_shell.py,sha256=46_m49Txc5q1rGfCgO49ca48BODx45DQJi8D0zz1R18,4245
|
152
152
|
meerschaum/config/_sync.py,sha256=nN5bLCHU8sFDdlPi7pQXuRVFcX457rZjOiALTvqRS_E,4332
|
153
|
-
meerschaum/config/_version.py,sha256=
|
153
|
+
meerschaum/config/_version.py,sha256=Q8imWbF1NIK8GFKpklTRimzU-PqJRTShxG3q0jm90X8,74
|
154
154
|
meerschaum/config/paths.py,sha256=JjibeGN3YAdSNceRwsd42aNmeUrIgM6ndzC8qZAmNI0,621
|
155
155
|
meerschaum/config/static.py,sha256=92fSGxoHFDOK9GEsN8NVbAEh9W7-eZ1BS6thyEqcjeI,359
|
156
156
|
meerschaum/config/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -190,13 +190,13 @@ meerschaum/connectors/sql/_cli.py,sha256=D4c_S-xTmhLRxl2dMhNSF0bMb1fDrMwWP2SVRBm
|
|
190
190
|
meerschaum/connectors/sql/_create_engine.py,sha256=vAoM8oBZHLikF7gVCMMOfe19MF-xw3kFj1mL0HUOD7o,7531
|
191
191
|
meerschaum/connectors/sql/_fetch.py,sha256=eJIqVAc4qI0xrbkZedO85sfB1-Hd3_Jkk12D6-OuzRU,12208
|
192
192
|
meerschaum/connectors/sql/_instance.py,sha256=xCc8M0xWMzF5Tu_1uWIFivAoHey5N1ccFhN_Z7u04zk,6304
|
193
|
-
meerschaum/connectors/sql/_pipes.py,sha256=
|
193
|
+
meerschaum/connectors/sql/_pipes.py,sha256=3gVhXUrBAo90GOKxnvSVNiKqkh6NaLT8cHSJ6tVRE2A,130040
|
194
194
|
meerschaum/connectors/sql/_plugins.py,sha256=SubR5HUJaetoUCv83YNEMwhv4wTTBCMcxSOEUgyMML4,8747
|
195
195
|
meerschaum/connectors/sql/_sql.py,sha256=7x54ED3WYNASBBb50JKX37-d-LLQsp2fqR59S7qK6HQ,44490
|
196
196
|
meerschaum/connectors/sql/_uri.py,sha256=BFzu5pjlbL3kxLH13vHWlpKGYTPfg8wuA2j58O9NsCM,3440
|
197
197
|
meerschaum/connectors/sql/_users.py,sha256=Gzsy2JDowdmJ2oiZlq07MmrZx2mfU3NLMUSSdO7blIg,10593
|
198
198
|
meerschaum/connectors/sql/tools.py,sha256=jz8huOaRCwGlYdtGfAqAh7SoK8uydYBrasKQba9FT38,187
|
199
|
-
meerschaum/connectors/sql/tables/__init__.py,sha256=
|
199
|
+
meerschaum/connectors/sql/tables/__init__.py,sha256=DphdLWgztzNGIDDZcjq8c8YO-mqq6q4nDKEN5k0DQG4,13345
|
200
200
|
meerschaum/connectors/sql/tables/types.py,sha256=Jc_MTHIBM-KHpQt__Lckp39CeOo7tGOiAk5faDx-znY,1573
|
201
201
|
meerschaum/connectors/valkey/_ValkeyConnector.py,sha256=QkhfipUHl5bN0sTmG-m90sr_RD4ukUmW9MY3COCv3Mw,15820
|
202
202
|
meerschaum/connectors/valkey/__init__.py,sha256=jkVutsygQCvGPLN17cP6wHAjHajxVycnQJbm2eVMuY0,187
|
@@ -205,7 +205,7 @@ meerschaum/connectors/valkey/_pipes.py,sha256=G1kHIll1sEUiCPGvTodDYrfplJ4ixHlJ0l
|
|
205
205
|
meerschaum/connectors/valkey/_plugins.py,sha256=KjNE2RDJ90b96ynoPz30iOiWU86bfJjFX70bhkXDcGM,5774
|
206
206
|
meerschaum/connectors/valkey/_users.py,sha256=AS1vLarrkDA9yPK644GWwRiQiTZVa9x3nlLpyntq40g,7730
|
207
207
|
meerschaum/core/__init__.py,sha256=Qx0s4KANuYCjTCHEaE70cfgCPxiYPPkr9DnmCTw33Z0,291
|
208
|
-
meerschaum/core/Pipe/__init__.py,sha256=
|
208
|
+
meerschaum/core/Pipe/__init__.py,sha256=7b0uZmtyOuqWWcraRBHZuR-oh1oT97vzvt-8GawOByo,21264
|
209
209
|
meerschaum/core/Pipe/_attributes.py,sha256=bXPvGwKfpCukmma2g6G_q2TILRvPu-s4mq-DLpQbIes,32451
|
210
210
|
meerschaum/core/Pipe/_bootstrap.py,sha256=4RLDD25BvqyukHhejTIJFaECOvCgZk6tjtNQfS9qgA8,8150
|
211
211
|
meerschaum/core/Pipe/_clear.py,sha256=LghXabgyyc1tD7FNQrh9ExT71ipcg2poM9FDA3k9e4M,2230
|
@@ -239,13 +239,13 @@ meerschaum/models/users.py,sha256=E1ambl2g6f2tdnLkwAquyqjvflrb2AMiVhI9nXXHYR0,68
|
|
239
239
|
meerschaum/plugins/__init__.py,sha256=Kf9Z7aiyNkEpR6M9f3pXWiOJ8u1hiLknpQqISgzBmMI,27362
|
240
240
|
meerschaum/plugins/bootstrap.py,sha256=sSvdh2g78AYwTTNMTdHw62Nj2v95pmbd77HFznuErUE,27728
|
241
241
|
meerschaum/utils/__init__.py,sha256=QrK1K9hIbPCRCM5k2nZGFqGnrqhA0Eh-iSmCU7FG6Cs,612
|
242
|
-
meerschaum/utils/_get_pipes.py,sha256=
|
242
|
+
meerschaum/utils/_get_pipes.py,sha256=TbV77VjQ9qqCLOy06-hlnfQI_hS6PTcXkbO7aQ2csdM,13275
|
243
243
|
meerschaum/utils/dataframe.py,sha256=JDf8Gus9ZrCKdOrcHcefsPxudbKinuadD9rH9LocLEg,67612
|
244
244
|
meerschaum/utils/debug.py,sha256=WqVBG0J5q0GckvuQNTKhFcqbEm0BuXP5v6PZq4osaCc,3635
|
245
245
|
meerschaum/utils/interactive.py,sha256=t-6jWozXSqL7lYGDHuwiOjTgr-UKhdcg61q_eR5mikI,3196
|
246
246
|
meerschaum/utils/misc.py,sha256=rHNvwg55V3iGxRaPog2X3uLbv_s_UR5mG3tRcVX-v44,50766
|
247
247
|
meerschaum/utils/networking.py,sha256=Sr_eYUGW8_UV9-k9LqRFf7xLtbUcsDucODyLCRsFRUc,1006
|
248
|
-
meerschaum/utils/pipes.py,sha256=
|
248
|
+
meerschaum/utils/pipes.py,sha256=SVIOXNg_YTTDfPssVIJKjMDJKZlCmDnALBvIRHhNuMI,5647
|
249
249
|
meerschaum/utils/pool.py,sha256=vkE42af4fjrTEJTxf6Ek3xGucm1MtEkpsSEiaVzNKHs,2655
|
250
250
|
meerschaum/utils/process.py,sha256=7iObszskRYLCf35GZGRigLLPDo5dugtzjM_SwSDX_uk,8219
|
251
251
|
meerschaum/utils/prompt.py,sha256=yTx03RXL5nsGtHrj7bjK72g1cA1inplLsw1vMSCtzPo,19444
|
@@ -266,18 +266,18 @@ meerschaum/utils/dtypes/sql.py,sha256=bVBzpagFLPJKYvW3EaQyPa6WkpBEHtllVL38r4CUBI
|
|
266
266
|
meerschaum/utils/formatting/__init__.py,sha256=UKQoCMtAWolpBtXVFHCKcCKfH9iKa1GaTbpy0wCYyB8,15531
|
267
267
|
meerschaum/utils/formatting/_jobs.py,sha256=izsqPJhTtUkXUUtWnbXtReYsUYwulXtci3pBj72Ne64,6637
|
268
268
|
meerschaum/utils/formatting/_pipes.py,sha256=4nrDkfwoEq434TbEChG0v1HuRZ8Pn1EKPhTJL64ez-Y,19555
|
269
|
-
meerschaum/utils/formatting/_pprint.py,sha256=
|
269
|
+
meerschaum/utils/formatting/_pprint.py,sha256=DCwopIQUu2xsCETsmbfSYVupG6Uz95gyZ63pa_nDMPo,3097
|
270
270
|
meerschaum/utils/formatting/_shell.py,sha256=kCxvO3NJ5COWVRSKfOXXeuMiyxTloe0OhEtglzuZKGs,3798
|
271
271
|
meerschaum/utils/packages/__init__.py,sha256=_qa99_yeAHLuXkAys5KCY2XyC-IJtksHl5Nk_GQV4eY,63669
|
272
272
|
meerschaum/utils/packages/_packages.py,sha256=jxTUz9dZOg_fNd19-hliz3zTbmA22VUnk0nxIT7nGyA,9371
|
273
273
|
meerschaum/utils/packages/lazy_loader.py,sha256=VHnph3VozH29R4JnSSBfwtA5WKZYZQFT_GeQSShCnuc,2540
|
274
274
|
meerschaum/utils/venv/_Venv.py,sha256=dF-FqP7Boq-g-anj2Ps-UkTOL2qJtxY3bdz0HWF2zT8,3726
|
275
275
|
meerschaum/utils/venv/__init__.py,sha256=E2JqbfddMrv1Yrlq-iUiok2grgzW5gUQt9y4EG68gm8,27265
|
276
|
-
meerschaum-3.0.
|
277
|
-
meerschaum-3.0.
|
278
|
-
meerschaum-3.0.
|
279
|
-
meerschaum-3.0.
|
280
|
-
meerschaum-3.0.
|
281
|
-
meerschaum-3.0.
|
282
|
-
meerschaum-3.0.
|
283
|
-
meerschaum-3.0.
|
276
|
+
meerschaum-3.0.0rc4.dist-info/licenses/LICENSE,sha256=jG2zQEdRNt88EgHUWPpXVWmOrOduUQRx7MnYV9YIPaw,11359
|
277
|
+
meerschaum-3.0.0rc4.dist-info/licenses/NOTICE,sha256=OTA9Fcthjf5BRvWDDIcBC_xfLpeDV-RPZh3M-HQBRtQ,114
|
278
|
+
meerschaum-3.0.0rc4.dist-info/METADATA,sha256=PwoaKQBKmWrnqpCkFvhMTYN2bSxInQeKm63psANDPPk,25227
|
279
|
+
meerschaum-3.0.0rc4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
280
|
+
meerschaum-3.0.0rc4.dist-info/entry_points.txt,sha256=5YBVzibw-0rNA_1VjB16z5GABsOGf-CDhW4yqH8C7Gc,88
|
281
|
+
meerschaum-3.0.0rc4.dist-info/top_level.txt,sha256=bNoSiDj0El6buocix-FRoAtJOeq1qOF5rRm2u9i7Q6A,11
|
282
|
+
meerschaum-3.0.0rc4.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
283
|
+
meerschaum-3.0.0rc4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|