meerschaum 3.0.0rc1__py3-none-any.whl → 3.0.0rc3__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/_internal/arguments/_parser.py +2 -1
- meerschaum/_internal/docs/index.py +49 -2
- meerschaum/_internal/shell/Shell.py +5 -4
- meerschaum/_internal/static.py +8 -24
- meerschaum/actions/bootstrap.py +1 -1
- meerschaum/actions/edit.py +6 -3
- meerschaum/actions/start.py +1 -1
- meerschaum/actions/verify.py +5 -8
- meerschaum/api/__init__.py +2 -1
- meerschaum/api/dash/__init__.py +0 -2
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/dashboard.py +20 -19
- meerschaum/api/dash/callbacks/jobs.py +11 -5
- meerschaum/api/dash/callbacks/pipes.py +106 -5
- meerschaum/api/dash/callbacks/settings/__init__.py +0 -1
- meerschaum/api/dash/callbacks/{settings/tokens.py → tokens.py} +1 -1
- meerschaum/api/dash/jobs.py +1 -1
- meerschaum/api/dash/pages/__init__.py +2 -1
- meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
- meerschaum/api/dash/pages/pipes.py +4 -3
- meerschaum/api/dash/pages/settings/__init__.py +0 -1
- meerschaum/api/dash/pages/{settings/tokens.py → tokens.py} +6 -8
- meerschaum/api/dash/pipes.py +131 -0
- meerschaum/api/dash/tokens.py +28 -31
- meerschaum/api/routes/_pipes.py +47 -37
- meerschaum/config/_default.py +13 -2
- meerschaum/config/_paths.py +1 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +9 -8
- meerschaum/connectors/api/_pipes.py +2 -18
- meerschaum/connectors/api/_tokens.py +2 -2
- meerschaum/connectors/instance/_tokens.py +10 -6
- meerschaum/connectors/sql/_SQLConnector.py +14 -0
- meerschaum/connectors/sql/_create_engine.py +3 -14
- meerschaum/connectors/sql/_pipes.py +175 -185
- meerschaum/connectors/sql/_sql.py +38 -20
- meerschaum/connectors/sql/tables/__init__.py +237 -122
- meerschaum/connectors/valkey/_pipes.py +44 -16
- meerschaum/core/Pipe/__init__.py +28 -5
- meerschaum/core/Pipe/_attributes.py +273 -46
- meerschaum/core/Pipe/_data.py +55 -17
- meerschaum/core/Pipe/_dtypes.py +19 -4
- meerschaum/core/Pipe/_edit.py +2 -0
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_sync.py +90 -160
- meerschaum/core/Pipe/_verify.py +3 -3
- meerschaum/core/Token/_Token.py +4 -5
- meerschaum/plugins/bootstrap.py +508 -3
- meerschaum/utils/_get_pipes.py +1 -1
- meerschaum/utils/dataframe.py +385 -68
- meerschaum/utils/debug.py +15 -15
- meerschaum/utils/dtypes/__init__.py +387 -22
- meerschaum/utils/dtypes/sql.py +327 -31
- meerschaum/utils/misc.py +9 -68
- meerschaum/utils/packages/__init__.py +7 -21
- meerschaum/utils/packages/_packages.py +7 -2
- meerschaum/utils/schedule.py +1 -1
- meerschaum/utils/sql.py +8 -8
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/METADATA +5 -17
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/RECORD +66 -65
- meerschaum-3.0.0rc3.dist-info/licenses/NOTICE +2 -0
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/zip-safe +0 -0
@@ -11,11 +11,14 @@ from meerschaum.utils.packages import import_html, import_dcc
|
|
11
11
|
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
12
12
|
import dash_bootstrap_components as dbc
|
13
13
|
|
14
|
-
from meerschaum.api.dash.components import download_logs, refresh_jobs_interval
|
14
|
+
from meerschaum.api.dash.components import download_logs, refresh_jobs_interval, pages_navbar
|
15
15
|
|
16
|
-
layout =
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
layout = [
|
17
|
+
pages_navbar,
|
18
|
+
dbc.Container([
|
19
|
+
dcc.Location('job-location'),
|
20
|
+
html.Div(id='job-output-div'),
|
21
|
+
download_logs,
|
22
|
+
refresh_jobs_interval,
|
23
|
+
]),
|
24
|
+
]
|
@@ -7,16 +7,17 @@ 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 download_dataframe, pages_navbar
|
10
|
+
from meerschaum.api.dash.components import download_dataframe, pages_navbar, navbar
|
11
11
|
|
12
12
|
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
13
13
|
import dash_bootstrap_components as dbc
|
14
14
|
|
15
|
+
|
15
16
|
layout = [
|
16
17
|
pages_navbar,
|
18
|
+
dcc.Location('pipes-location'),
|
19
|
+
download_dataframe,
|
17
20
|
dbc.Container([
|
18
|
-
dcc.Location('pipes-location'),
|
19
|
-
download_dataframe,
|
20
21
|
html.Div(id='pipe-output-div'),
|
21
22
|
])
|
22
23
|
]
|
@@ -8,16 +8,13 @@ Define the tokens page layout.
|
|
8
8
|
import dash_bootstrap_components as dbc
|
9
9
|
import dash.html as html
|
10
10
|
import dash.dcc as dcc
|
11
|
-
from meerschaum.plugins import web_page
|
12
11
|
from meerschaum._internal.static import STATIC_CONFIG
|
12
|
+
from meerschaum.api.dash.components import pages_navbar
|
13
13
|
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Return the layout for the tokens page.
|
19
|
-
"""
|
20
|
-
return dbc.Container([
|
15
|
+
layout = [
|
16
|
+
pages_navbar,
|
17
|
+
dbc.Container([
|
21
18
|
html.Br(),
|
22
19
|
html.H3('Tokens'),
|
23
20
|
html.Div(id="tokens-alert-div"),
|
@@ -52,4 +49,5 @@ def page_layout():
|
|
52
49
|
style={'text-align': 'right'},
|
53
50
|
),
|
54
51
|
html.Div(id='tokens-output-div'),
|
55
|
-
])
|
52
|
+
]),
|
53
|
+
]
|
meerschaum/api/dash/pipes.py
CHANGED
@@ -12,6 +12,7 @@ import shlex
|
|
12
12
|
from textwrap import dedent
|
13
13
|
from urllib.parse import urlencode
|
14
14
|
|
15
|
+
from meerschaum.utils import fetch_pipes_keys
|
15
16
|
from meerschaum.utils.typing import List, Optional, Dict, Any, Tuple, Union
|
16
17
|
from meerschaum.utils.misc import string_to_dict
|
17
18
|
from meerschaum.utils.packages import attempt_import, import_dcc, import_html, import_pandas
|
@@ -817,3 +818,133 @@ def get_backtrack_text(
|
|
817
818
|
json_text = '[]'
|
818
819
|
|
819
820
|
return json.dumps(json.loads(json_text), indent=4, separators=(',', ': '))
|
821
|
+
|
822
|
+
|
823
|
+
def build_pipes_dropdown_keys_row(
|
824
|
+
connector_keys: List[str],
|
825
|
+
metric_keys: List[str],
|
826
|
+
location_keys: List[str],
|
827
|
+
tags: List[str],
|
828
|
+
pipes: List[mrsm.Pipe],
|
829
|
+
instance_connector: mrsm.connectors.InstanceConnector,
|
830
|
+
) -> dbc.Row:
|
831
|
+
"""
|
832
|
+
Return the dropdown keys row for the dedicated pipes page.
|
833
|
+
"""
|
834
|
+
ck_alone = connector_keys and not any([str(x) for x in (tags + metric_keys + location_keys)])
|
835
|
+
mk_alone = metric_keys and not any([str(x) for x in (connector_keys + tags + location_keys)])
|
836
|
+
lk_alone = location_keys and not any([str(x) for x in (connector_keys + metric_keys + tags)])
|
837
|
+
all_keys = fetch_pipes_keys('registered', instance_connector)
|
838
|
+
return dbc.Row(
|
839
|
+
[
|
840
|
+
dbc.Col(
|
841
|
+
html.Div(
|
842
|
+
[
|
843
|
+
dcc.Dropdown(
|
844
|
+
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
|
+
),
|
850
|
+
value=[str(ck) for ck in connector_keys],
|
851
|
+
placeholder='Connectors',
|
852
|
+
multi=True,
|
853
|
+
),
|
854
|
+
],
|
855
|
+
className='dbc_dark',
|
856
|
+
),
|
857
|
+
lg=4,
|
858
|
+
md=12,
|
859
|
+
sm=12,
|
860
|
+
),
|
861
|
+
dbc.Col(
|
862
|
+
html.Div(
|
863
|
+
[
|
864
|
+
dcc.Dropdown(
|
865
|
+
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
|
+
),
|
871
|
+
value=[str(mk) for mk in metric_keys],
|
872
|
+
placeholder='Metrics',
|
873
|
+
multi=True,
|
874
|
+
),
|
875
|
+
],
|
876
|
+
className='dbc_dark'
|
877
|
+
),
|
878
|
+
lg=4,
|
879
|
+
md=12,
|
880
|
+
sm=12,
|
881
|
+
),
|
882
|
+
dbc.Col(
|
883
|
+
html.Div(
|
884
|
+
[
|
885
|
+
dcc.Dropdown(
|
886
|
+
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
|
+
),
|
892
|
+
value=[str(lk) for lk in location_keys],
|
893
|
+
placeholder='Locations',
|
894
|
+
multi=True,
|
895
|
+
),
|
896
|
+
],
|
897
|
+
className='dbc_dark'
|
898
|
+
),
|
899
|
+
lg=4,
|
900
|
+
md=12,
|
901
|
+
sm=12,
|
902
|
+
),
|
903
|
+
] ### end of filters row children
|
904
|
+
)
|
905
|
+
|
906
|
+
|
907
|
+
def build_pipes_tags_dropdown(
|
908
|
+
connector_keys: List[str],
|
909
|
+
metric_keys: List[str],
|
910
|
+
location_keys: List[str],
|
911
|
+
tags: List[str],
|
912
|
+
instance: str,
|
913
|
+
) -> html.Div:
|
914
|
+
"""
|
915
|
+
Build the tags dropdown for the dedicated pipes page.
|
916
|
+
"""
|
917
|
+
_tags_alone = tags and not any([str(x) for x in (connector_keys + metric_keys + location_keys)])
|
918
|
+
_tags_pipes = mrsm.get_pipes(
|
919
|
+
connector_keys=connector_keys,
|
920
|
+
metric_keys=metric_keys,
|
921
|
+
location_keys=location_keys,
|
922
|
+
tags=tags,
|
923
|
+
instance=instance,
|
924
|
+
as_tags_dict=True,
|
925
|
+
)
|
926
|
+
|
927
|
+
_all_tags = list(
|
928
|
+
mrsm.get_pipes(
|
929
|
+
instance=instance,
|
930
|
+
as_tags_dict=True,
|
931
|
+
)
|
932
|
+
) if _tags_alone else []
|
933
|
+
|
934
|
+
tags_options = [
|
935
|
+
str(tag)
|
936
|
+
for tag in (_all_tags if _tags_alone else _tags_pipes)
|
937
|
+
]
|
938
|
+
|
939
|
+
return html.Div(
|
940
|
+
dcc.Dropdown(
|
941
|
+
id='pipes-tags-dropdown',
|
942
|
+
options=tags_options,
|
943
|
+
value=tags,
|
944
|
+
placeholder='Tags',
|
945
|
+
multi=True,
|
946
|
+
searchable=True,
|
947
|
+
),
|
948
|
+
className="dbc_dark",
|
949
|
+
id="pipes-tags-dropdown-div",
|
950
|
+
)
|
meerschaum/api/dash/tokens.py
CHANGED
@@ -9,7 +9,7 @@ Dash utility functions for constructing tokens components.
|
|
9
9
|
from __future__ import annotations
|
10
10
|
|
11
11
|
from datetime import datetime, timezone, timedelta
|
12
|
-
from typing import Any, List
|
12
|
+
from typing import Any, List, Optional
|
13
13
|
|
14
14
|
import meerschaum as mrsm
|
15
15
|
from meerschaum.api import debug, CHECK_UPDATE, get_api_connector
|
@@ -18,8 +18,8 @@ from meerschaum.api.dash.components import alert_from_success_tuple
|
|
18
18
|
from meerschaum.api.dash.sessions import get_user_from_session
|
19
19
|
from meerschaum.utils.typing import WebState, SuccessTuple, List, Tuple
|
20
20
|
from meerschaum.utils.packages import attempt_import, import_html, import_dcc
|
21
|
-
from meerschaum.utils.misc import interval_str
|
22
|
-
from meerschaum.utils.dtypes import value_is_null
|
21
|
+
from meerschaum.utils.misc import interval_str
|
22
|
+
from meerschaum.utils.dtypes import value_is_null, round_time
|
23
23
|
from meerschaum._internal.static import STATIC_CONFIG
|
24
24
|
from meerschaum.core import Token
|
25
25
|
from meerschaum.utils.daemon import get_new_daemon_name
|
@@ -91,39 +91,36 @@ def build_manage_token_popover(token: Token) -> dbc.Popover:
|
|
91
91
|
"""
|
92
92
|
return dbc.Popover(
|
93
93
|
[
|
94
|
-
dbc.
|
95
|
-
|
96
|
-
dbc.ButtonGroup(
|
97
|
-
([
|
98
|
-
dbc.Button(
|
99
|
-
"Edit",
|
100
|
-
outline=True,
|
101
|
-
color='light',
|
102
|
-
id={
|
103
|
-
'type': 'tokens-edit-button',
|
104
|
-
'index': str(token.id),
|
105
|
-
},
|
106
|
-
),
|
107
|
-
dbc.Button(
|
108
|
-
"Invalidate",
|
109
|
-
outline=True,
|
110
|
-
color='warning',
|
111
|
-
id={
|
112
|
-
'type': 'tokens-invalidate-button',
|
113
|
-
'index': str(token.id),
|
114
|
-
},
|
115
|
-
),
|
116
|
-
] if token.is_valid else []) + [
|
94
|
+
dbc.ButtonGroup(
|
95
|
+
([
|
117
96
|
dbc.Button(
|
118
|
-
"
|
119
|
-
color='danger',
|
97
|
+
"Edit",
|
120
98
|
outline=True,
|
99
|
+
color='light',
|
121
100
|
id={
|
122
|
-
'type': 'tokens-
|
101
|
+
'type': 'tokens-edit-button',
|
123
102
|
'index': str(token.id),
|
124
103
|
},
|
125
104
|
),
|
126
|
-
|
105
|
+
dbc.Button(
|
106
|
+
"Invalidate",
|
107
|
+
outline=True,
|
108
|
+
color='warning',
|
109
|
+
id={
|
110
|
+
'type': 'tokens-invalidate-button',
|
111
|
+
'index': str(token.id),
|
112
|
+
},
|
113
|
+
),
|
114
|
+
] if token.is_valid else []) + [
|
115
|
+
dbc.Button(
|
116
|
+
"Delete",
|
117
|
+
color='danger',
|
118
|
+
outline=True,
|
119
|
+
id={
|
120
|
+
'type': 'tokens-delete-button',
|
121
|
+
'index': str(token.id),
|
122
|
+
},
|
123
|
+
),
|
127
124
|
]),
|
128
125
|
],
|
129
126
|
body=True,
|
@@ -600,7 +597,7 @@ def build_tokens_register_output_modal(token: Token) -> List[Any]:
|
|
600
597
|
dbc.Button(
|
601
598
|
"Close",
|
602
599
|
id='tokens-close-register-output-modal-button',
|
603
|
-
disabled=
|
600
|
+
disabled=success,
|
604
601
|
),
|
605
602
|
]),
|
606
603
|
]
|
meerschaum/api/routes/_pipes.py
CHANGED
@@ -23,9 +23,7 @@ from meerschaum.api import (
|
|
23
23
|
pipes,
|
24
24
|
get_pipe,
|
25
25
|
_get_pipes,
|
26
|
-
manager,
|
27
26
|
debug,
|
28
|
-
no_auth,
|
29
27
|
ScopedAuth,
|
30
28
|
)
|
31
29
|
from meerschaum.models import (
|
@@ -74,7 +72,7 @@ def register_pipe(
|
|
74
72
|
instance_keys: Optional[str] = None,
|
75
73
|
parameters: Optional[Dict[str, Any]] = None,
|
76
74
|
curr_user = fastapi.Security(ScopedAuth(['pipes:write']), scopes=['pipes:write']),
|
77
|
-
) ->
|
75
|
+
) -> mrsm.SuccessTuple:
|
78
76
|
"""
|
79
77
|
Register a new pipe.
|
80
78
|
"""
|
@@ -94,8 +92,9 @@ def register_pipe(
|
|
94
92
|
)
|
95
93
|
if parameters:
|
96
94
|
pipe.parameters = parameters
|
95
|
+
|
97
96
|
success, msg = get_api_connector(instance_keys).register_pipe(pipe, debug=debug)
|
98
|
-
pipes(instance_keys, refresh=True)
|
97
|
+
_ = pipes(instance_keys, refresh=True)
|
99
98
|
return success, msg
|
100
99
|
|
101
100
|
|
@@ -112,7 +111,7 @@ def edit_pipe(
|
|
112
111
|
instance_keys: Optional[str] = None,
|
113
112
|
patch: bool = False,
|
114
113
|
curr_user = fastapi.Security(ScopedAuth(['pipes:write'])),
|
115
|
-
) ->
|
114
|
+
) -> mrsm.SuccessTuple:
|
116
115
|
"""
|
117
116
|
Edit an existing pipe's parameters.
|
118
117
|
"""
|
@@ -125,14 +124,16 @@ def edit_pipe(
|
|
125
124
|
" Under the keys `api:permissions:actions`, "
|
126
125
|
"you can toggle non-admin actions."
|
127
126
|
)
|
127
|
+
|
128
128
|
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
129
129
|
if not is_pipe_registered(pipe, pipes(instance_keys, refresh=True)):
|
130
130
|
raise fastapi.HTTPException(
|
131
131
|
status_code=409, detail=f"{pipe} is not registered."
|
132
132
|
)
|
133
|
+
|
133
134
|
pipe.parameters = parameters
|
134
135
|
success, msg = get_api_connector(instance_keys).edit_pipe(pipe, patch=patch, debug=debug)
|
135
|
-
pipes(instance_keys, refresh=True)
|
136
|
+
_ = pipes(instance_keys, refresh=True)
|
136
137
|
return success, msg
|
137
138
|
|
138
139
|
|
@@ -147,7 +148,7 @@ def delete_pipe(
|
|
147
148
|
location_key: str,
|
148
149
|
instance_keys: Optional[str] = None,
|
149
150
|
curr_user = fastapi.Security(ScopedAuth(['pipes:delete'])),
|
150
|
-
) ->
|
151
|
+
) -> SuccessTuple:
|
151
152
|
"""
|
152
153
|
Delete a Pipe (without dropping its table).
|
153
154
|
"""
|
@@ -156,9 +157,10 @@ def delete_pipe(
|
|
156
157
|
raise fastapi.HTTPException(
|
157
158
|
status_code=409, detail=f"{pipe} is not registered."
|
158
159
|
)
|
159
|
-
|
160
|
-
|
161
|
-
|
160
|
+
|
161
|
+
success, msg = get_api_connector(instance_keys).delete_pipe(pipe, debug=debug)
|
162
|
+
_ = pipes(instance_keys, refresh=True)
|
163
|
+
return success, msg
|
162
164
|
|
163
165
|
|
164
166
|
@app.get(
|
@@ -207,6 +209,7 @@ async def get_pipes(
|
|
207
209
|
kw['metric_keys'] = metric_keys
|
208
210
|
if location_keys != "":
|
209
211
|
kw['location_keys'] = location_keys
|
212
|
+
|
210
213
|
pipes_dict = replace_pipes_in_dict(_get_pipes(**kw), lambda p: p.attributes)
|
211
214
|
for metrics in pipes_dict.values():
|
212
215
|
for locations in metrics.values():
|
@@ -224,14 +227,19 @@ async def get_pipes_by_connector(
|
|
224
227
|
"""
|
225
228
|
Get all registered Pipes by connector_keys with metadata, excluding parameters.
|
226
229
|
"""
|
227
|
-
if connector_keys not in pipes(instance_keys):
|
230
|
+
if connector_keys not in pipes(instance_keys, refresh=True):
|
228
231
|
raise fastapi.HTTPException(
|
229
232
|
status_code=404, detail=f"Connector '{connector_keys}' not found."
|
230
233
|
)
|
231
|
-
|
234
|
+
|
235
|
+
metrics = replace_pipes_in_dict(
|
236
|
+
pipes(instance_keys, refresh=False)[connector_keys],
|
237
|
+
lambda p: p.attributes
|
238
|
+
)
|
232
239
|
for locations in metrics.values():
|
233
240
|
if None in locations:
|
234
241
|
locations['None'] = locations.pop(None)
|
242
|
+
|
235
243
|
return metrics
|
236
244
|
|
237
245
|
|
@@ -245,22 +253,26 @@ async def get_pipes_by_connector_and_metric(
|
|
245
253
|
"""
|
246
254
|
Get all registered Pipes by `connector_keys` and `metric_key` with metadata, excluding parameters.
|
247
255
|
"""
|
248
|
-
if connector_keys not in pipes(instance_keys):
|
256
|
+
if connector_keys not in pipes(instance_keys, refresh=True):
|
249
257
|
raise fastapi.HTTPException(
|
250
258
|
status_code=404,
|
251
259
|
detail=f"Connector '{connector_keys}' not found.",
|
252
260
|
)
|
253
|
-
|
261
|
+
|
262
|
+
if metric_key not in pipes(instance_keys, refresh=False)[connector_keys]:
|
254
263
|
raise fastapi.HTTPException(
|
255
264
|
status_code=404,
|
256
265
|
detail=f"Metric '{metric_key}' not found.",
|
257
266
|
)
|
267
|
+
|
258
268
|
locations = replace_pipes_in_dict(
|
259
|
-
pipes(instance_keys)[connector_keys][metric_key],
|
269
|
+
pipes(instance_keys, refresh=False)[connector_keys][metric_key],
|
260
270
|
lambda p: p.attributes
|
261
271
|
)
|
272
|
+
|
262
273
|
if None in locations:
|
263
274
|
locations['None'] = locations.pop(None)
|
275
|
+
|
264
276
|
return locations
|
265
277
|
|
266
278
|
|
@@ -278,22 +290,25 @@ async def get_pipe_by_connector_and_metric_and_location(
|
|
278
290
|
"""
|
279
291
|
Get a specific Pipe with metadata, excluding parameters.
|
280
292
|
"""
|
281
|
-
if connector_keys not in pipes(instance_keys):
|
293
|
+
if connector_keys not in pipes(instance_keys, refresh=True):
|
282
294
|
raise fastapi.HTTPException(
|
283
295
|
status_code=404,
|
284
296
|
detail=f"Connector '{connector_keys}' not found.",
|
285
297
|
)
|
286
|
-
|
298
|
+
|
299
|
+
if metric_key not in pipes(instance_keys, refresh=False)[connector_keys]:
|
287
300
|
raise fastapi.HTTPException(status_code=404, detail=f"Metric '{metric_key}' not found.")
|
301
|
+
|
288
302
|
if location_key in ('[None]', 'None', 'null'):
|
289
303
|
location_key = None
|
290
|
-
|
304
|
+
|
305
|
+
if location_key not in pipes(instance_keys, refresh=False)[connector_keys][metric_key]:
|
291
306
|
raise fastapi.HTTPException(
|
292
307
|
status_code=404,
|
293
308
|
detail=f"location_key '{location_key}' not found."
|
294
309
|
)
|
295
310
|
|
296
|
-
return pipes(instance_keys)[connector_keys][metric_key][location_key].attributes
|
311
|
+
return pipes(instance_keys, refresh=False)[connector_keys][metric_key][location_key].attributes
|
297
312
|
|
298
313
|
|
299
314
|
@app.get(
|
@@ -397,7 +412,7 @@ async def sync_pipe(
|
|
397
412
|
detail="Cannot sync given data.",
|
398
413
|
)
|
399
414
|
|
400
|
-
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
415
|
+
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys, refresh=True)
|
401
416
|
if pipe.target in ('mrsm_users', 'mrsm_plugins', 'mrsm_pipes', 'mrsm_tokens'):
|
402
417
|
raise fastapi.HTTPException(
|
403
418
|
status_code=409,
|
@@ -616,23 +631,14 @@ def drop_pipe(
|
|
616
631
|
location_key: str,
|
617
632
|
instance_keys: Optional[str] = None,
|
618
633
|
curr_user = fastapi.Security(ScopedAuth(['pipes:drop'])),
|
619
|
-
) ->
|
634
|
+
) -> mrsm.SuccessTuple:
|
620
635
|
"""
|
621
636
|
Drop a pipe's target table.
|
622
637
|
"""
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
"Please contact the system administrator, or if you are running this server, "
|
628
|
-
"open the configuration file with `edit config system` and search for 'permissions'."
|
629
|
-
" Under the keys `api:permissions:actions`, " +
|
630
|
-
"you can toggle non-admin actions."
|
631
|
-
)
|
632
|
-
pipe_object = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
633
|
-
results = get_api_connector(instance_keys=instance_keys).drop_pipe(pipe_object, debug=debug)
|
634
|
-
pipes(instance_keys, refresh=True)
|
635
|
-
return results
|
638
|
+
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
639
|
+
success, msg = pipe.drop(debug=debug)
|
640
|
+
_ = pipes(instance_keys, refresh=True)
|
641
|
+
return success, msg
|
636
642
|
|
637
643
|
|
638
644
|
@app.delete(
|
@@ -661,6 +667,7 @@ def clear_pipe(
|
|
661
667
|
_params = json.loads(params)
|
662
668
|
except Exception:
|
663
669
|
_params = None
|
670
|
+
|
664
671
|
if not isinstance(_params, dict):
|
665
672
|
raise fastapi.HTTPException(
|
666
673
|
status_code=409,
|
@@ -676,7 +683,7 @@ def clear_pipe(
|
|
676
683
|
params=_params,
|
677
684
|
debug=debug,
|
678
685
|
)
|
679
|
-
pipes(instance_keys, refresh=True)
|
686
|
+
_ = pipes(instance_keys, refresh=True)
|
680
687
|
return results
|
681
688
|
|
682
689
|
|
@@ -894,8 +901,11 @@ def get_pipe_columns_types(
|
|
894
901
|
```
|
895
902
|
"""
|
896
903
|
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
897
|
-
columns_types =
|
898
|
-
|
904
|
+
columns_types = (
|
905
|
+
pipe.get_columns_types(debug=debug)
|
906
|
+
or pipe.get_dtypes(refresh=True, debug=debug)
|
907
|
+
)
|
908
|
+
return columns_types
|
899
909
|
|
900
910
|
|
901
911
|
@app.get(
|
meerschaum/config/_default.py
CHANGED
@@ -99,6 +99,7 @@ default_system_config = {
|
|
99
99
|
'mssql': True,
|
100
100
|
},
|
101
101
|
'instance': {
|
102
|
+
'create_metadata_cache_minutes': 14400,
|
102
103
|
'stale_temporary_tables_minutes': 1440,
|
103
104
|
'temporary_target': {
|
104
105
|
'prefix': '_',
|
@@ -199,14 +200,25 @@ default_pipes_config = {
|
|
199
200
|
},
|
200
201
|
},
|
201
202
|
'attributes': {
|
202
|
-
'local_cache_timeout_seconds':
|
203
|
+
'local_cache_timeout_seconds': 600.0,
|
203
204
|
},
|
204
205
|
'sync': {
|
205
206
|
'filter_params_index_limit': 250,
|
207
|
+
'exists_cache_seconds': 60.0,
|
206
208
|
},
|
207
209
|
'verify': {
|
208
210
|
'max_chunks_syncs': 3,
|
209
211
|
},
|
212
|
+
'autotime': {
|
213
|
+
'column_name_if_datetime_missing': 'ts',
|
214
|
+
},
|
215
|
+
'dtypes': {
|
216
|
+
'min_ratio_columns_changed_for_full_astype': 0.5,
|
217
|
+
'columns_types_cache_seconds': 60.0,
|
218
|
+
},
|
219
|
+
'static': {
|
220
|
+
'static_schema_cache_seconds': 3600.0,
|
221
|
+
},
|
210
222
|
}
|
211
223
|
default_plugins_config = {}
|
212
224
|
default_experimental_config = {
|
@@ -214,7 +226,6 @@ default_experimental_config = {
|
|
214
226
|
}
|
215
227
|
|
216
228
|
|
217
|
-
|
218
229
|
### build default config dictionary
|
219
230
|
default_config = {}
|
220
231
|
default_config['meerschaum'] = default_meerschaum_config
|
meerschaum/config/_paths.py
CHANGED
@@ -149,6 +149,7 @@ paths = {
|
|
149
149
|
'PIPES_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'pipes'),
|
150
150
|
'USERS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'users'),
|
151
151
|
'VENVS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'venvs'),
|
152
|
+
'SQL_CONN_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'sql'),
|
152
153
|
|
153
154
|
'PLUGINS_RESOURCES_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins'),
|
154
155
|
'PLUGINS_INTERNAL_LOCK_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins.lock'),
|
meerschaum/config/_version.py
CHANGED
@@ -122,9 +122,9 @@ default_docker_compose_config = {
|
|
122
122
|
'POSTGRES_DB': '<DOLLAR>POSTGRES_DB',
|
123
123
|
'POSTGRES_PASSWORD': '<DOLLAR>POSTGRES_PASSWORD',
|
124
124
|
'ALLOW_IP_RANGE': env_dict['ALLOW_IP_RANGE'],
|
125
|
-
'POSTGRES_INITDB_ARGS': '-c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100'
|
125
|
+
# 'POSTGRES_INITDB_ARGS': '-c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100'
|
126
126
|
},
|
127
|
-
|
127
|
+
'command': 'postgres -c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100',
|
128
128
|
'healthcheck': {
|
129
129
|
'test': [
|
130
130
|
'CMD-SHELL', 'pg_isready -d <DOLLAR>POSTGRES_DB -U <DOLLAR>POSTGRES_USER',
|
@@ -305,19 +305,20 @@ def get_necessary_files():
|
|
305
305
|
|
306
306
|
|
307
307
|
def write_stack(
|
308
|
-
|
309
|
-
|
308
|
+
debug: bool = False
|
309
|
+
):
|
310
310
|
"""Write Docker Compose configuration files."""
|
311
311
|
from meerschaum.config._edit import general_write_yaml_config
|
312
312
|
from meerschaum.config._sync import sync_files
|
313
313
|
general_write_yaml_config(get_necessary_files(), debug=debug)
|
314
314
|
return sync_files(['stack'])
|
315
315
|
|
316
|
+
|
316
317
|
def edit_stack(
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
318
|
+
action: Optional[List[str]] = None,
|
319
|
+
debug: bool = False,
|
320
|
+
**kw
|
321
|
+
):
|
321
322
|
"""Open docker-compose.yaml or .env for editing."""
|
322
323
|
from meerschaum.config._edit import general_edit_config
|
323
324
|
if action is None:
|