meerschaum 2.3.5.dev0__py3-none-any.whl → 2.4.0__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/__init__.py +2 -1
- meerschaum/_internal/arguments/_parse_arguments.py +88 -12
- meerschaum/_internal/docs/index.py +3 -2
- meerschaum/_internal/entry.py +42 -20
- meerschaum/_internal/shell/Shell.py +38 -44
- meerschaum/_internal/term/TermPageHandler.py +2 -3
- meerschaum/_internal/term/__init__.py +13 -11
- meerschaum/actions/api.py +26 -23
- meerschaum/actions/bootstrap.py +38 -11
- meerschaum/actions/copy.py +3 -3
- meerschaum/actions/delete.py +4 -1
- meerschaum/actions/register.py +1 -3
- meerschaum/actions/stack.py +24 -19
- meerschaum/actions/start.py +41 -41
- meerschaum/actions/sync.py +53 -52
- meerschaum/api/__init__.py +48 -14
- meerschaum/api/_events.py +26 -17
- meerschaum/api/_oauth2.py +2 -2
- meerschaum/api/_websockets.py +5 -4
- meerschaum/api/dash/__init__.py +7 -16
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/dashboard.py +52 -58
- meerschaum/api/dash/callbacks/jobs.py +15 -16
- meerschaum/api/dash/callbacks/login.py +16 -10
- meerschaum/api/dash/callbacks/pipes.py +41 -0
- meerschaum/api/dash/callbacks/plugins.py +1 -1
- meerschaum/api/dash/callbacks/register.py +15 -11
- meerschaum/api/dash/components.py +54 -59
- meerschaum/api/dash/jobs.py +5 -9
- meerschaum/api/dash/pages/__init__.py +1 -0
- meerschaum/api/dash/pages/pipes.py +19 -0
- meerschaum/api/dash/pipes.py +86 -58
- meerschaum/api/dash/plugins.py +6 -4
- meerschaum/api/dash/sessions.py +176 -0
- meerschaum/api/dash/users.py +3 -41
- meerschaum/api/dash/webterm.py +12 -17
- meerschaum/api/resources/static/js/terminado.js +1 -1
- meerschaum/api/routes/_actions.py +4 -118
- meerschaum/api/routes/_jobs.py +45 -24
- meerschaum/api/routes/_login.py +4 -4
- meerschaum/api/routes/_pipes.py +3 -3
- meerschaum/api/routes/_webterm.py +5 -6
- meerschaum/config/_default.py +15 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +64 -21
- meerschaum/config/static/__init__.py +6 -0
- meerschaum/connectors/{Connector.py → _Connector.py} +19 -13
- meerschaum/connectors/__init__.py +24 -14
- meerschaum/connectors/api/{APIConnector.py → _APIConnector.py} +3 -1
- meerschaum/connectors/api/__init__.py +2 -1
- meerschaum/connectors/api/_actions.py +22 -36
- meerschaum/connectors/api/_jobs.py +1 -0
- meerschaum/connectors/parse.py +18 -16
- meerschaum/connectors/poll.py +30 -24
- meerschaum/connectors/sql/__init__.py +3 -1
- meerschaum/connectors/sql/_pipes.py +172 -197
- meerschaum/connectors/sql/_plugins.py +45 -43
- meerschaum/connectors/sql/_users.py +46 -38
- meerschaum/connectors/valkey/_ValkeyConnector.py +535 -0
- meerschaum/connectors/valkey/__init__.py +10 -0
- meerschaum/connectors/valkey/_fetch.py +75 -0
- meerschaum/connectors/valkey/_pipes.py +844 -0
- meerschaum/connectors/valkey/_plugins.py +265 -0
- meerschaum/connectors/valkey/_users.py +305 -0
- meerschaum/core/Pipe/__init__.py +3 -0
- meerschaum/core/Pipe/_attributes.py +1 -2
- meerschaum/core/Pipe/_clear.py +16 -13
- meerschaum/core/Pipe/_copy.py +106 -0
- meerschaum/core/Pipe/_data.py +165 -101
- meerschaum/core/Pipe/_drop.py +4 -4
- meerschaum/core/Pipe/_dtypes.py +14 -14
- meerschaum/core/Pipe/_edit.py +15 -14
- meerschaum/core/Pipe/_sync.py +134 -53
- meerschaum/core/Pipe/_verify.py +11 -11
- meerschaum/core/User/_User.py +14 -12
- meerschaum/jobs/_Job.py +27 -14
- meerschaum/jobs/__init__.py +7 -2
- meerschaum/jobs/systemd.py +20 -8
- meerschaum/plugins/_Plugin.py +17 -13
- meerschaum/utils/_get_pipes.py +14 -20
- meerschaum/utils/dataframe.py +291 -101
- meerschaum/utils/dtypes/__init__.py +31 -6
- meerschaum/utils/dtypes/sql.py +4 -4
- meerschaum/utils/formatting/_shell.py +5 -6
- meerschaum/utils/misc.py +3 -3
- meerschaum/utils/packages/__init__.py +14 -9
- meerschaum/utils/packages/_packages.py +2 -0
- meerschaum/utils/prompt.py +1 -1
- meerschaum/utils/schedule.py +1 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/METADATA +7 -1
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/RECORD +98 -89
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/WHEEL +1 -1
- meerschaum/api/dash/actions.py +0 -255
- /meerschaum/connectors/sql/{SQLConnector.py → _SQLConnector.py} +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/zip-safe +0 -0
meerschaum/api/__init__.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
Meerschaum API backend. Start an API instance with `start api`.
|
7
7
|
"""
|
8
8
|
from __future__ import annotations
|
9
|
-
import
|
9
|
+
import os
|
10
10
|
from meerschaum.utils.typing import Dict, Any, Optional
|
11
11
|
|
12
12
|
from meerschaum import __version__ as version
|
@@ -21,7 +21,7 @@ from meerschaum.utils.packages import attempt_import
|
|
21
21
|
from meerschaum.utils import get_pipes as _get_pipes
|
22
22
|
from meerschaum.config._paths import API_UVICORN_CONFIG_PATH, API_UVICORN_RESOURCES_PATH
|
23
23
|
from meerschaum.plugins import _api_plugins
|
24
|
-
from meerschaum.utils.warnings import warn
|
24
|
+
from meerschaum.utils.warnings import warn, dprint
|
25
25
|
from meerschaum.utils.threading import RLock
|
26
26
|
|
27
27
|
_locks = {'pipes': RLock(), 'connector': RLock(), 'uvicorn_config': RLock()}
|
@@ -44,8 +44,8 @@ uv = attempt_import('uv', lazy=False, check_update=CHECK_UPDATE)
|
|
44
44
|
'starlette.responses',
|
45
45
|
'multipart',
|
46
46
|
'packaging.version',
|
47
|
-
lazy
|
48
|
-
check_update
|
47
|
+
lazy=False,
|
48
|
+
check_update=CHECK_UPDATE,
|
49
49
|
)
|
50
50
|
(
|
51
51
|
typing_extensions,
|
@@ -53,9 +53,9 @@ uv = attempt_import('uv', lazy=False, check_update=CHECK_UPDATE)
|
|
53
53
|
) = attempt_import(
|
54
54
|
'typing_extensions',
|
55
55
|
'uvicorn.workers',
|
56
|
-
lazy
|
57
|
-
check_update
|
58
|
-
venv
|
56
|
+
lazy=False,
|
57
|
+
check_update=CHECK_UPDATE,
|
58
|
+
venv=None,
|
59
59
|
)
|
60
60
|
from meerschaum.api._chain import check_allow_chaining, DISALLOW_CHAINING_MESSAGE
|
61
61
|
uvicorn_config_path = API_UVICORN_RESOURCES_PATH / SERVER_ID / 'config.json'
|
@@ -75,7 +75,7 @@ def get_uvicorn_config() -> Dict[str, Any]:
|
|
75
75
|
with _locks['uvicorn_config']:
|
76
76
|
if uvicorn_config is None:
|
77
77
|
try:
|
78
|
-
with open(uvicorn_config_path, 'r') as f:
|
78
|
+
with open(uvicorn_config_path, 'r', encoding='utf-8') as f:
|
79
79
|
uvicorn_config = json.load(f)
|
80
80
|
_uvicorn_config = uvicorn_config
|
81
81
|
except Exception as e:
|
@@ -93,12 +93,12 @@ debug = get_uvicorn_config().get('debug', False)
|
|
93
93
|
no_dash = get_uvicorn_config().get('no_dash', False)
|
94
94
|
no_auth = get_uvicorn_config().get('no_auth', False)
|
95
95
|
private = get_uvicorn_config().get('private', False)
|
96
|
+
production = get_uvicorn_config().get('production', False)
|
96
97
|
_include_dash = (not no_dash)
|
97
98
|
|
98
99
|
connector = None
|
99
100
|
def get_api_connector(instance_keys: Optional[str] = None):
|
100
101
|
"""Create the instance connector."""
|
101
|
-
from meerschaum.utils.debug import dprint
|
102
102
|
global connector
|
103
103
|
with _locks['connector']:
|
104
104
|
if connector is None:
|
@@ -111,6 +111,40 @@ def get_api_connector(instance_keys: Optional[str] = None):
|
|
111
111
|
dprint(f"API instance connector: {connector}")
|
112
112
|
return connector
|
113
113
|
|
114
|
+
cache_connector = None
|
115
|
+
def get_cache_connector(connector_keys: Optional[str] = None):
|
116
|
+
"""Return the `valkey` connector if running in production."""
|
117
|
+
global cache_connector
|
118
|
+
if cache_connector is not None:
|
119
|
+
return cache_connector
|
120
|
+
|
121
|
+
if not production:
|
122
|
+
return None
|
123
|
+
|
124
|
+
enable_valkey_cache = get_config('system', 'experimental', 'valkey_session_cache')
|
125
|
+
if not enable_valkey_cache:
|
126
|
+
return None
|
127
|
+
|
128
|
+
connector_keys = connector_keys or get_config(
|
129
|
+
'system', 'api', 'cache', 'connector',
|
130
|
+
warn=False,
|
131
|
+
)
|
132
|
+
if connector_keys is None:
|
133
|
+
return None
|
134
|
+
|
135
|
+
if not connector_keys.startswith('valkey'):
|
136
|
+
warn(f"Invalid cache connector '{connector_keys}'.")
|
137
|
+
return None
|
138
|
+
|
139
|
+
if cache_connector is None:
|
140
|
+
from meerschaum.connectors.parse import parse_instance_keys
|
141
|
+
cache_connector = parse_instance_keys(connector_keys)
|
142
|
+
|
143
|
+
if debug:
|
144
|
+
dprint(f"Cache connector: {cache_connector}")
|
145
|
+
|
146
|
+
return cache_connector
|
147
|
+
|
114
148
|
|
115
149
|
_pipes = None
|
116
150
|
def pipes(refresh=False):
|
@@ -138,17 +172,17 @@ def get_pipe(connector_keys, metric_key, location_key, refresh=False):
|
|
138
172
|
|
139
173
|
app = fastapi.FastAPI(
|
140
174
|
title = 'Meerschaum API',
|
141
|
-
description
|
142
|
-
version
|
143
|
-
contact
|
175
|
+
description=__doc__,
|
176
|
+
version=__version__,
|
177
|
+
contact={
|
144
178
|
'name': 'Bennett Meares',
|
145
179
|
'url': 'https://meerschaum.io',
|
146
180
|
},
|
147
|
-
license_info
|
181
|
+
license_info={
|
148
182
|
'name': 'Apache 2.0',
|
149
183
|
'url': 'https://www.apache.org/licenses/LICENSE-2.0.html',
|
150
184
|
},
|
151
|
-
open_api_tags
|
185
|
+
open_api_tags=[
|
152
186
|
{
|
153
187
|
'name': 'Pipes',
|
154
188
|
'description': 'Access pipes by indexing their keys.',
|
meerschaum/api/_events.py
CHANGED
@@ -6,26 +6,29 @@
|
|
6
6
|
Declare FastAPI events in this module (startup, shutdown, etc.).
|
7
7
|
"""
|
8
8
|
|
9
|
-
import sys
|
9
|
+
import sys
|
10
|
+
import os
|
11
|
+
import time
|
10
12
|
from meerschaum.api import (
|
11
13
|
app,
|
12
14
|
get_api_connector,
|
15
|
+
get_cache_connector,
|
13
16
|
get_uvicorn_config,
|
14
17
|
debug,
|
15
18
|
no_dash,
|
16
|
-
uvicorn_config_path,
|
17
19
|
)
|
18
20
|
from meerschaum.utils.debug import dprint
|
19
21
|
from meerschaum.connectors.poll import retry_connect
|
20
22
|
from meerschaum.utils.warnings import warn
|
21
|
-
from meerschaum._internal.term.tools import is_webterm_running
|
22
23
|
from meerschaum.jobs import (
|
24
|
+
get_jobs,
|
23
25
|
start_check_jobs_thread,
|
24
26
|
stop_check_jobs_thread,
|
25
|
-
get_executor_keys_from_context,
|
26
27
|
)
|
28
|
+
from meerschaum.config.static import STATIC_CONFIG
|
29
|
+
|
30
|
+
TEMP_PREFIX: str = STATIC_CONFIG['api']['jobs']['temp_prefix']
|
27
31
|
|
28
|
-
_check_jobs_thread = None
|
29
32
|
|
30
33
|
@app.on_event("startup")
|
31
34
|
async def startup():
|
@@ -39,10 +42,17 @@ async def startup():
|
|
39
42
|
|
40
43
|
connected = retry_connect(
|
41
44
|
get_api_connector(),
|
42
|
-
workers
|
43
|
-
debug
|
45
|
+
workers=get_uvicorn_config().get('workers', None),
|
46
|
+
debug=debug
|
44
47
|
)
|
45
|
-
|
48
|
+
cache_connector = get_cache_connector()
|
49
|
+
if cache_connector is not None:
|
50
|
+
connected = retry_connect(
|
51
|
+
cache_connector,
|
52
|
+
workers=get_uvicorn_config().get('workers', None),
|
53
|
+
debug=debug,
|
54
|
+
)
|
55
|
+
except Exception:
|
46
56
|
import traceback
|
47
57
|
traceback.print_exc()
|
48
58
|
connected = False
|
@@ -51,8 +61,7 @@ async def startup():
|
|
51
61
|
await shutdown()
|
52
62
|
os._exit(1)
|
53
63
|
|
54
|
-
|
55
|
-
start_check_jobs_thread()
|
64
|
+
start_check_jobs_thread()
|
56
65
|
|
57
66
|
|
58
67
|
@app.on_event("shutdown")
|
@@ -65,17 +74,17 @@ async def shutdown():
|
|
65
74
|
if get_api_connector().type == 'sql':
|
66
75
|
get_api_connector().engine.dispose()
|
67
76
|
|
68
|
-
|
69
|
-
stop_check_jobs_thread()
|
77
|
+
stop_check_jobs_thread()
|
70
78
|
|
71
|
-
|
72
|
-
|
79
|
+
temp_jobs = {
|
80
|
+
name: job
|
81
|
+
for name, job in get_jobs(include_hidden=True).items()
|
82
|
+
if name.startswith(TEMP_PREFIX)
|
83
|
+
}
|
84
|
+
for job in temp_jobs.values():
|
73
85
|
job.delete()
|
74
86
|
|
75
87
|
### Terminate any running jobs left over.
|
76
88
|
if 'meerschaum.api.dash' in sys.modules:
|
77
|
-
from meerschaum.api.dash.actions import running_jobs, stop_action
|
78
89
|
from meerschaum.api.dash.webterm import stop_webterm
|
79
90
|
stop_webterm()
|
80
|
-
for session_id in running_jobs:
|
81
|
-
stop_action({'session-store.data': {'session-id': session_id}})
|
meerschaum/api/_oauth2.py
CHANGED
@@ -39,10 +39,10 @@ def generate_secret_key() -> str:
|
|
39
39
|
from meerschaum.config._paths import API_SECRET_KEY_PATH
|
40
40
|
if not API_SECRET_KEY_PATH.exists():
|
41
41
|
secret_key = os.urandom(24).hex()
|
42
|
-
with open(API_SECRET_KEY_PATH, 'w+') as f:
|
42
|
+
with open(API_SECRET_KEY_PATH, 'w+', encoding='utf-8') as f:
|
43
43
|
f.write(secret_key)
|
44
44
|
else:
|
45
|
-
with open(API_SECRET_KEY_PATH, 'r') as f:
|
45
|
+
with open(API_SECRET_KEY_PATH, 'r', encoding='utf-8') as f:
|
46
46
|
secret_key = f.read()
|
47
47
|
|
48
48
|
return secret_key.encode('utf-8')
|
meerschaum/api/_websockets.py
CHANGED
@@ -6,13 +6,13 @@
|
|
6
6
|
Implement WebSockets for the Meerschaum API via FastAPI.
|
7
7
|
"""
|
8
8
|
|
9
|
-
import time, uuid
|
10
9
|
from datetime import datetime, timezone
|
10
|
+
|
11
11
|
from meerschaum.api import (
|
12
|
-
app,
|
12
|
+
app,
|
13
|
+
fastapi,
|
14
|
+
endpoints,
|
13
15
|
)
|
14
|
-
from meerschaum.api.dash.users import is_session_authenticated
|
15
|
-
from meerschaum.utils.typing import Optional
|
16
16
|
|
17
17
|
_websocket_endpoint = endpoints['websocket']
|
18
18
|
|
@@ -28,6 +28,7 @@ async def websocket_endpoint(
|
|
28
28
|
"""
|
29
29
|
Communicate with the Web Interface over a websocket.
|
30
30
|
"""
|
31
|
+
from meerschaum.api.dash.sessions import is_session_authenticated
|
31
32
|
await websocket.accept()
|
32
33
|
try:
|
33
34
|
initial_data = await websocket.receive_json()
|
meerschaum/api/dash/__init__.py
CHANGED
@@ -16,7 +16,6 @@ flask_compress = attempt_import('flask_compress', lazy=False)
|
|
16
16
|
_monkey_patch_get_distribution('flask-compress', flask_compress.__version__)
|
17
17
|
dash = attempt_import('dash', lazy=False)
|
18
18
|
|
19
|
-
|
20
19
|
from meerschaum.utils.typing import List, Optional
|
21
20
|
from meerschaum.config.static import _static_config
|
22
21
|
from meerschaum.api import (
|
@@ -38,14 +37,6 @@ with warnings.catch_warnings():
|
|
38
37
|
html, dcc = import_html(), import_dcc()
|
39
38
|
from meerschaum.api.dash.components import location
|
40
39
|
|
41
|
-
active_sessions = {}
|
42
|
-
authenticated_sessions = {}
|
43
|
-
unauthenticated_sessions = {}
|
44
|
-
running_jobs = {}
|
45
|
-
running_monitors = {}
|
46
|
-
stopped_jobs = {}
|
47
|
-
stopped_monitors = {}
|
48
|
-
|
49
40
|
stylesheets = [
|
50
41
|
'/static/css/bootstrap.min.css',
|
51
42
|
'/static/css/dbc_dark.css',
|
@@ -54,12 +45,12 @@ stylesheets = [
|
|
54
45
|
scripts = ['/static/js/node_modules/xterm/lib/xterm.js']
|
55
46
|
dash_app = enrich.DashProxy(
|
56
47
|
__name__,
|
57
|
-
title
|
58
|
-
requests_pathname_prefix
|
59
|
-
external_stylesheets
|
60
|
-
update_title
|
61
|
-
suppress_callback_exceptions
|
62
|
-
transforms
|
48
|
+
title='Meerschaum Web',
|
49
|
+
requests_pathname_prefix=endpoints['dash'] + '/',
|
50
|
+
external_stylesheets=stylesheets,
|
51
|
+
update_title=None,
|
52
|
+
suppress_callback_exceptions=True,
|
53
|
+
transforms=[
|
63
54
|
enrich.TriggerTransform(),
|
64
55
|
enrich.MultiplexerTransform(),
|
65
56
|
],
|
@@ -67,7 +58,7 @@ dash_app = enrich.DashProxy(
|
|
67
58
|
|
68
59
|
dash_app.layout = html.Div([
|
69
60
|
location,
|
70
|
-
dcc.Store(id='session-store', storage_type='
|
61
|
+
dcc.Store(id='session-store', storage_type='local', data={}),
|
71
62
|
html.Div([], id='page-layout-div'),
|
72
63
|
])
|
73
64
|
|
@@ -11,6 +11,7 @@ import meerschaum.api.dash.callbacks.login
|
|
11
11
|
import meerschaum.api.dash.callbacks.plugins
|
12
12
|
import meerschaum.api.dash.callbacks.jobs
|
13
13
|
import meerschaum.api.dash.callbacks.register
|
14
|
+
import meerschaum.api.dash.callbacks.pipes
|
14
15
|
from meerschaum.api.dash.callbacks.custom import init_dash_plugins, add_plugin_pages
|
15
16
|
|
16
17
|
init_dash_plugins()
|
@@ -7,18 +7,21 @@ Callbacks for the main dashboard.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
|
10
|
+
|
11
|
+
import textwrap
|
12
|
+
import json
|
13
|
+
import uuid
|
11
14
|
from dash.dependencies import Input, Output, State, ALL, MATCH
|
12
15
|
from dash.exceptions import PreventUpdate
|
13
|
-
from meerschaum.config import get_config
|
14
|
-
from meerschaum.config.static import _static_config
|
15
16
|
from meerschaum.utils.typing import List, Optional, Any, Tuple
|
16
17
|
from meerschaum.api import get_api_connector, endpoints, no_auth, CHECK_UPDATE
|
17
|
-
from meerschaum.api.dash import
|
18
|
-
|
19
|
-
|
18
|
+
from meerschaum.api.dash import dash_app, debug
|
19
|
+
from meerschaum.api.dash.sessions import (
|
20
|
+
is_session_active,
|
21
|
+
delete_session,
|
22
|
+
set_session,
|
20
23
|
)
|
21
|
-
from meerschaum.api.dash.
|
24
|
+
from meerschaum.api.dash.sessions import is_session_authenticated
|
22
25
|
from meerschaum.api.dash.connectors import get_web_connector
|
23
26
|
from meerschaum.connectors.parse import parse_instance_keys
|
24
27
|
from meerschaum.api.dash.pipes import get_pipes_cards, pipe_from_ctx, accordion_items_from_pipe
|
@@ -30,21 +33,14 @@ from meerschaum.api.dash.webterm import get_webterm
|
|
30
33
|
from meerschaum.api.dash.components import (
|
31
34
|
alert_from_success_tuple, console_div, build_cards_grid,
|
32
35
|
)
|
33
|
-
from meerschaum.api.dash
|
34
|
-
import meerschaum.api.dash.pages as pages
|
36
|
+
from meerschaum.api.dash import pages
|
35
37
|
from meerschaum.utils.typing import Dict
|
36
|
-
from meerschaum.utils.debug import dprint
|
37
38
|
from meerschaum.utils.packages import attempt_import, import_html, import_dcc
|
38
|
-
from meerschaum.utils.misc import
|
39
|
-
string_to_dict, get_connector_labels, json_serialize_datetime, filter_keywords,
|
40
|
-
flatten_list,
|
41
|
-
)
|
39
|
+
from meerschaum.utils.misc import filter_keywords, flatten_list
|
42
40
|
from meerschaum.utils.yaml import yaml
|
43
41
|
from meerschaum.actions import get_subactions, actions
|
44
|
-
from meerschaum._internal.arguments._parser import
|
42
|
+
from meerschaum._internal.arguments._parser import parser
|
45
43
|
from meerschaum.connectors.sql._fetch import set_pipe_query
|
46
|
-
import meerschaum as mrsm
|
47
|
-
import json
|
48
44
|
dash = attempt_import('dash', lazy=False, check_update=CHECK_UPDATE)
|
49
45
|
dbc = attempt_import('dash_bootstrap_components', lazy=False, check_update=CHECK_UPDATE)
|
50
46
|
dcc, html = import_dcc(check_update=CHECK_UPDATE), import_html(check_update=CHECK_UPDATE)
|
@@ -101,6 +97,7 @@ _paths = {
|
|
101
97
|
'' : pages.dashboard.layout,
|
102
98
|
'plugins' : pages.plugins.layout,
|
103
99
|
'register': pages.register.layout,
|
100
|
+
'pipes' : pages.pipes.layout,
|
104
101
|
}
|
105
102
|
_required_login = {''}
|
106
103
|
|
@@ -108,21 +105,21 @@ _required_login = {''}
|
|
108
105
|
@dash_app.callback(
|
109
106
|
Output('page-layout-div', 'children'),
|
110
107
|
Output('session-store', 'data'),
|
111
|
-
Input('location', 'pathname'),
|
108
|
+
Input('mrsm-location', 'pathname'),
|
112
109
|
Input('session-store', 'data'),
|
113
|
-
State('location', 'href'),
|
110
|
+
State('mrsm-location', 'href'),
|
114
111
|
)
|
115
112
|
def update_page_layout_div(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
113
|
+
pathname: str,
|
114
|
+
session_store_data: Dict[str, Any],
|
115
|
+
location_href: str,
|
116
|
+
) -> Tuple[List[Any], Dict[str, Any]]:
|
120
117
|
"""
|
121
118
|
Route the user to the correct page.
|
122
119
|
|
123
120
|
Parameters
|
124
121
|
----------
|
125
|
-
pathname: str
|
122
|
+
pathname: str
|
126
123
|
The path in the browser.
|
127
124
|
|
128
125
|
session_store_data: Dict[str, Any]:
|
@@ -132,20 +129,19 @@ def update_page_layout_div(
|
|
132
129
|
-------
|
133
130
|
A tuple of the page layout and new session store data.
|
134
131
|
"""
|
135
|
-
ctx = dash.callback_context
|
136
132
|
dash_endpoint = endpoints['dash']
|
137
133
|
try:
|
138
|
-
session_id = session_store_data.get('session-id', None)
|
134
|
+
session_id = session_store_data.get('session-id', None)
|
139
135
|
except AttributeError:
|
140
136
|
session_id = None
|
141
137
|
|
142
138
|
### Bypass login if `--no-auth` is specified.
|
143
|
-
if
|
139
|
+
if not is_session_active(session_id) and no_auth:
|
144
140
|
session_store_data['session-id'] = str(uuid.uuid4())
|
145
|
-
|
141
|
+
set_session(session_id, {'username': 'no-auth'})
|
146
142
|
|
147
143
|
### Sometimes the href is an empty string, so store it here for later.
|
148
|
-
session_store_data['location.href'] = location_href
|
144
|
+
session_store_data['mrsm-location.href'] = location_href
|
149
145
|
session_store_to_return = session_store_data
|
150
146
|
else:
|
151
147
|
session_store_to_return = dash.no_update
|
@@ -175,7 +171,7 @@ def update_page_layout_div(
|
|
175
171
|
path_str
|
176
172
|
if no_auth or path_str not in _required_login else (
|
177
173
|
path_str
|
178
|
-
if session_id
|
174
|
+
if is_session_active(session_id)
|
179
175
|
else 'login'
|
180
176
|
)
|
181
177
|
)
|
@@ -194,7 +190,7 @@ def update_page_layout_div(
|
|
194
190
|
Input('get-plugins-button', 'n_clicks'),
|
195
191
|
Input('get-users-button', 'n_clicks'),
|
196
192
|
Input('get-graphs-button', 'n_clicks'),
|
197
|
-
State('location', 'href'),
|
193
|
+
State('mrsm-location', 'href'),
|
198
194
|
State('session-store', 'data'),
|
199
195
|
State('webterm-div', 'children'),
|
200
196
|
*keys_state,
|
@@ -205,7 +201,6 @@ def update_content(*args):
|
|
205
201
|
and execute the appropriate function.
|
206
202
|
"""
|
207
203
|
ctx = dash.callback_context
|
208
|
-
location_href = ctx.states['session-store.data'].get('location.href', None)
|
209
204
|
session_id = ctx.states['session-store.data'].get('session-id', None)
|
210
205
|
authenticated = is_session_authenticated(str(session_id))
|
211
206
|
|
@@ -237,9 +232,6 @@ def update_content(*args):
|
|
237
232
|
'get-pipes-button': 1,
|
238
233
|
'get-jobs-button': 2,
|
239
234
|
}
|
240
|
-
|
241
|
-
### NOTE: stop the running action if it exists
|
242
|
-
stop_action(ctx.states)
|
243
235
|
|
244
236
|
content, alerts = triggers[trigger](
|
245
237
|
ctx.states,
|
@@ -311,9 +303,9 @@ dash_app.clientside_callback(
|
|
311
303
|
return url;
|
312
304
|
}
|
313
305
|
""",
|
314
|
-
Output('location', 'href'),
|
306
|
+
Output('mrsm-location', 'href'),
|
315
307
|
Input('go-button', 'n_clicks'),
|
316
|
-
State('location', 'href'),
|
308
|
+
State('mrsm-location', 'href'),
|
317
309
|
State('connector-keys-dropdown', 'value'),
|
318
310
|
State('metric-keys-dropdown', 'value'),
|
319
311
|
State('location-keys-dropdown', 'value'),
|
@@ -490,12 +482,12 @@ def update_flags(input_flags_dropdown_values, n_clicks, input_flags_texts):
|
|
490
482
|
*keys_state
|
491
483
|
)
|
492
484
|
def update_keys_options(
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
485
|
+
connector_keys: Optional[List[str]],
|
486
|
+
metric_keys: Optional[List[str]],
|
487
|
+
location_keys: Optional[List[str]],
|
488
|
+
instance_keys: Optional[str],
|
489
|
+
*keys
|
490
|
+
):
|
499
491
|
"""
|
500
492
|
Update the keys dropdown menus' options.
|
501
493
|
"""
|
@@ -543,9 +535,9 @@ def update_keys_options(
|
|
543
535
|
_keys = fetch_pipes_keys(
|
544
536
|
'registered',
|
545
537
|
get_web_connector(ctx.states),
|
546
|
-
connector_keys
|
547
|
-
metric_keys
|
548
|
-
location_keys
|
538
|
+
connector_keys=_ck_filter,
|
539
|
+
metric_keys=_mk_filter,
|
540
|
+
location_keys=_lk_filter,
|
549
541
|
)
|
550
542
|
except Exception as e:
|
551
543
|
instance_alerts += [alert_from_success_tuple((False, str(e)))]
|
@@ -637,7 +629,7 @@ dash_app.clientside_callback(
|
|
637
629
|
return url;
|
638
630
|
}
|
639
631
|
""",
|
640
|
-
Output('location', 'href'),
|
632
|
+
Output('mrsm-location', 'href'),
|
641
633
|
Input('instance-select', 'value'),
|
642
634
|
)
|
643
635
|
|
@@ -710,11 +702,12 @@ dash_app.clientside_callback(
|
|
710
702
|
return url;
|
711
703
|
}
|
712
704
|
""",
|
713
|
-
Output('location', 'href'),
|
705
|
+
Output('mrsm-location', 'href'),
|
714
706
|
Input('console-pre', 'children'),
|
715
|
-
State('location', 'href'),
|
707
|
+
State('mrsm-location', 'href'),
|
716
708
|
)
|
717
709
|
|
710
|
+
|
718
711
|
@dash_app.callback(
|
719
712
|
Output("download-dataframe-csv", "data"),
|
720
713
|
Input({'type': 'pipe-download-csv-button', 'index': ALL}, 'n_clicks'),
|
@@ -736,7 +729,7 @@ def download_pipe_csv(n_clicks):
|
|
736
729
|
filename = str(pipe.target) + f" {begin} - {end}.csv"
|
737
730
|
try:
|
738
731
|
df = pipe.get_data(begin=begin, end=end, debug=debug)
|
739
|
-
except Exception
|
732
|
+
except Exception:
|
740
733
|
df = None
|
741
734
|
if df is not None:
|
742
735
|
return dcc.send_data_frame(df.to_csv, filename, index=False)
|
@@ -749,6 +742,9 @@ def download_pipe_csv(n_clicks):
|
|
749
742
|
State('session-store', 'data'),
|
750
743
|
)
|
751
744
|
def update_pipe_accordion(item, session_store_data):
|
745
|
+
"""
|
746
|
+
Expand the pipe accordion item and lazy load.
|
747
|
+
"""
|
752
748
|
if item is None:
|
753
749
|
raise PreventUpdate
|
754
750
|
|
@@ -918,7 +914,7 @@ dash_app.clientside_callback(
|
|
918
914
|
""",
|
919
915
|
Output('content-div-right', 'children'),
|
920
916
|
Input({'type': 'manage-pipe-button', 'index': ALL, 'action': ALL}, 'n_clicks'),
|
921
|
-
State('location', 'href'),
|
917
|
+
State('mrsm-location', 'href'),
|
922
918
|
)
|
923
919
|
|
924
920
|
@dash_app.callback(
|
@@ -948,15 +944,15 @@ def toggle_navbar_collapse(n_clicks: Optional[int], is_open: bool) -> bool:
|
|
948
944
|
|
949
945
|
|
950
946
|
@dash_app.callback(
|
951
|
-
Output('location', 'pathname'),
|
947
|
+
Output('mrsm-location', 'pathname'),
|
952
948
|
Output('session-store', 'data'),
|
953
949
|
Input("sign-out-button", "n_clicks"),
|
954
950
|
State('session-store', 'data'),
|
955
951
|
)
|
956
952
|
def sign_out_button_click(
|
957
|
-
|
958
|
-
|
959
|
-
|
953
|
+
n_clicks: Optional[int],
|
954
|
+
session_store_data: Dict[str, Any],
|
955
|
+
):
|
960
956
|
"""
|
961
957
|
When the sign out button is clicked, remove the session data and redirect to the login page.
|
962
958
|
"""
|
@@ -964,9 +960,7 @@ def sign_out_button_click(
|
|
964
960
|
raise PreventUpdate
|
965
961
|
session_id = session_store_data.get('session-id', None)
|
966
962
|
if session_id:
|
967
|
-
|
968
|
-
_ = authenticated_sessions.pop(session_id, None)
|
969
|
-
_ = unauthenticated_sessions.pop(session_id, None)
|
963
|
+
delete_session(session_id)
|
970
964
|
return endpoints['dash'], {}
|
971
965
|
|
972
966
|
|
@@ -7,36 +7,35 @@ Callbacks for jobs' cards.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
+
|
10
11
|
import json
|
11
|
-
import functools
|
12
12
|
import time
|
13
13
|
import traceback
|
14
14
|
from datetime import datetime, timezone
|
15
|
-
import meerschaum as mrsm
|
16
15
|
from meerschaum.utils.typing import Optional, Dict, Any
|
17
|
-
from meerschaum.api import
|
18
|
-
from meerschaum.api.dash import dash_app
|
16
|
+
from meerschaum.api import CHECK_UPDATE
|
17
|
+
from meerschaum.api.dash import dash_app
|
18
|
+
from meerschaum.api.dash.sessions import get_username_from_session
|
19
19
|
from meerschaum.utils.packages import attempt_import, import_dcc, import_html
|
20
|
-
|
21
|
-
from dash.exceptions import PreventUpdate
|
22
|
-
from dash.dependencies import Input, Output, State, ALL, MATCH
|
23
|
-
from dash import Patch
|
24
|
-
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
25
|
-
import dash_bootstrap_components as dbc
|
26
|
-
from meerschaum.api.dash.components import alert_from_success_tuple, build_cards_grid
|
27
|
-
from dash.exceptions import PreventUpdate
|
20
|
+
from meerschaum.api.dash.components import alert_from_success_tuple
|
28
21
|
from meerschaum.api.dash.jobs import (
|
29
22
|
build_manage_job_buttons_div_children,
|
30
23
|
build_status_children,
|
31
24
|
build_process_timestamps_children,
|
32
25
|
)
|
33
26
|
from meerschaum.jobs import Job
|
34
|
-
from meerschaum.api.dash.
|
27
|
+
from meerschaum.api.dash.sessions import is_session_authenticated
|
28
|
+
dash = attempt_import('dash', lazy=False, check_update=CHECK_UPDATE)
|
29
|
+
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
30
|
+
from dash.exceptions import PreventUpdate
|
31
|
+
from dash.dependencies import Input, Output, State, ALL, MATCH
|
32
|
+
import dash_bootstrap_components as dbc
|
33
|
+
|
35
34
|
|
36
35
|
@dash_app.callback(
|
37
36
|
Output("download-logs", "data"),
|
38
37
|
Input({'type': 'job-download-logs-button', 'index': ALL}, 'n_clicks'),
|
39
|
-
prevent_initial_call
|
38
|
+
prevent_initial_call=True,
|
40
39
|
)
|
41
40
|
def download_job_logs(n_clicks):
|
42
41
|
"""
|
@@ -84,7 +83,7 @@ def manage_job_button_click(
|
|
84
83
|
raise PreventUpdate
|
85
84
|
|
86
85
|
session_id = session_data.get('session-id', None)
|
87
|
-
username =
|
86
|
+
username = get_username_from_session(session_id)
|
88
87
|
|
89
88
|
if not is_session_authenticated(session_id):
|
90
89
|
success, msg = False, f"User '{username}' is not authenticated to manage jobs."
|
@@ -182,7 +181,7 @@ dash_app.clientside_callback(
|
|
182
181
|
""",
|
183
182
|
Output('content-div-right', 'children'),
|
184
183
|
Input({'type': 'follow-logs-button', 'index': ALL}, 'n_clicks'),
|
185
|
-
State('location', 'href'),
|
184
|
+
State('mrsm-location', 'href'),
|
186
185
|
)
|
187
186
|
|
188
187
|
|