meerschaum 2.3.5.dev0__py3-none-any.whl → 2.4.0.dev0__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 +86 -7
- meerschaum/_internal/entry.py +29 -13
- meerschaum/actions/api.py +16 -16
- meerschaum/actions/bootstrap.py +36 -10
- meerschaum/actions/start.py +16 -15
- meerschaum/api/_events.py +11 -7
- meerschaum/api/dash/__init__.py +7 -6
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/dashboard.py +7 -5
- meerschaum/api/dash/callbacks/pipes.py +42 -0
- meerschaum/api/dash/pages/__init__.py +1 -0
- meerschaum/api/dash/pages/pipes.py +16 -0
- meerschaum/api/dash/pipes.py +79 -47
- meerschaum/api/dash/users.py +19 -6
- meerschaum/api/routes/_actions.py +0 -98
- meerschaum/api/routes/_jobs.py +38 -18
- meerschaum/api/routes/_login.py +4 -4
- meerschaum/api/routes/_pipes.py +3 -3
- meerschaum/config/_default.py +9 -2
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +59 -18
- meerschaum/config/static/__init__.py +2 -0
- meerschaum/connectors/Connector.py +19 -13
- meerschaum/connectors/__init__.py +9 -5
- meerschaum/connectors/api/_actions.py +22 -36
- meerschaum/connectors/api/_jobs.py +1 -0
- meerschaum/connectors/poll.py +30 -24
- meerschaum/connectors/sql/_pipes.py +126 -154
- 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 +8 -0
- meerschaum/connectors/valkey/_fetch.py +75 -0
- meerschaum/connectors/valkey/_pipes.py +839 -0
- meerschaum/connectors/valkey/_plugins.py +265 -0
- meerschaum/connectors/valkey/_users.py +305 -0
- meerschaum/core/Pipe/__init__.py +2 -0
- meerschaum/core/Pipe/_attributes.py +1 -2
- 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 -51
- meerschaum/core/User/_User.py +14 -12
- meerschaum/jobs/_Job.py +26 -8
- meerschaum/jobs/systemd.py +20 -8
- meerschaum/plugins/_Plugin.py +17 -13
- meerschaum/utils/_get_pipes.py +14 -20
- meerschaum/utils/dataframe.py +288 -101
- meerschaum/utils/dtypes/__init__.py +31 -6
- meerschaum/utils/dtypes/sql.py +4 -4
- meerschaum/utils/misc.py +3 -3
- meerschaum/utils/packages/_packages.py +1 -0
- meerschaum/utils/prompt.py +1 -1
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/METADATA +3 -1
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/RECORD +62 -54
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/WHEEL +1 -1
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/zip-safe +0 -0
@@ -9,7 +9,8 @@ This package includes argument parsing utilities.
|
|
9
9
|
from meerschaum._internal.arguments._parse_arguments import (
|
10
10
|
parse_arguments, parse_line, remove_leading_action,
|
11
11
|
parse_dict_to_sysargs, split_chained_sysargs, split_pipeline_sysargs,
|
12
|
-
sysargs_has_api_executor_keys,
|
12
|
+
sysargs_has_api_executor_keys, get_pipeline_sysargs,
|
13
|
+
compress_pipeline_sysargs, remove_api_executor_keys,
|
13
14
|
)
|
14
15
|
from meerschaum._internal.arguments._parser import parser
|
15
16
|
from meerschaum.plugins import add_plugin_argument
|
@@ -424,12 +424,91 @@ def sysargs_has_api_executor_keys(sysargs: List[str]) -> bool:
|
|
424
424
|
if '-e' not in sysargs and '--executor-keys' not in sysargs:
|
425
425
|
return False
|
426
426
|
|
427
|
-
|
428
|
-
|
429
|
-
|
427
|
+
for i, arg in enumerate(sysargs):
|
428
|
+
if arg not in ('-e', '--executor-keys'):
|
429
|
+
continue
|
430
430
|
|
431
|
-
|
432
|
-
|
431
|
+
executor_keys_ix = i + 1
|
432
|
+
if len(sysargs) <= executor_keys_ix:
|
433
|
+
return False
|
434
|
+
|
435
|
+
executor_keys = sysargs[executor_keys_ix]
|
436
|
+
if executor_keys.startswith('api:'):
|
437
|
+
return True
|
438
|
+
|
439
|
+
return False
|
440
|
+
|
441
|
+
|
442
|
+
def remove_api_executor_keys(sysargs: List[str]) -> List[str]:
|
443
|
+
"""
|
444
|
+
Remove any api executor keys from `sysargs`.
|
445
|
+
"""
|
446
|
+
from meerschaum.utils.misc import flatten_list
|
447
|
+
|
448
|
+
if not sysargs_has_api_executor_keys(sysargs):
|
449
|
+
return sysargs
|
450
|
+
|
451
|
+
skip_indices = set(flatten_list(
|
452
|
+
[
|
453
|
+
[i, i+1]
|
454
|
+
for i, arg in enumerate(sysargs)
|
455
|
+
if arg in ('-e', '--executor-keys')
|
456
|
+
]
|
457
|
+
))
|
458
|
+
|
459
|
+
return [
|
460
|
+
arg
|
461
|
+
for i, arg in enumerate(sysargs)
|
462
|
+
if i not in skip_indices
|
463
|
+
]
|
433
464
|
|
434
|
-
|
435
|
-
|
465
|
+
|
466
|
+
def get_pipeline_sysargs(
|
467
|
+
sysargs: List[str],
|
468
|
+
pipeline_args: List[str],
|
469
|
+
_patch_args: Optional[Dict[str, Any]] = None,
|
470
|
+
) -> List[str]:
|
471
|
+
"""
|
472
|
+
Parse `sysargs` and `pipeline_args` into a single `start pipeline` sysargs.
|
473
|
+
"""
|
474
|
+
import shlex
|
475
|
+
start_pipeline_params = {
|
476
|
+
'sub_args_line': shlex.join(sysargs),
|
477
|
+
'patch_args': _patch_args,
|
478
|
+
}
|
479
|
+
return (
|
480
|
+
['start', 'pipeline']
|
481
|
+
+ [str(arg) for arg in pipeline_args]
|
482
|
+
+ ['-P', json.dumps(start_pipeline_params, separators=(',', ':'))]
|
483
|
+
)
|
484
|
+
|
485
|
+
|
486
|
+
def compress_pipeline_sysargs(pipeline_sysargs: List[str]) -> List[str]:
|
487
|
+
"""
|
488
|
+
Given a `start pipeline` sysargs, return a condensed syntax rendition.
|
489
|
+
"""
|
490
|
+
import shlex
|
491
|
+
|
492
|
+
if pipeline_sysargs[:2] != ['start', 'pipeline']:
|
493
|
+
return pipeline_sysargs
|
494
|
+
|
495
|
+
if '-P' not in pipeline_sysargs:
|
496
|
+
return pipeline_sysargs
|
497
|
+
|
498
|
+
params_ix = pipeline_sysargs.index('-P')
|
499
|
+
pipeline_args = pipeline_sysargs[2:params_ix]
|
500
|
+
params_str = pipeline_sysargs[-1]
|
501
|
+
try:
|
502
|
+
start_pipeline_params = json.loads(params_str)
|
503
|
+
except Exception:
|
504
|
+
return pipeline_sysargs
|
505
|
+
|
506
|
+
sub_args_line = start_pipeline_params.get('sub_args_line', None)
|
507
|
+
if not sub_args_line:
|
508
|
+
return pipeline_sysargs
|
509
|
+
|
510
|
+
return (
|
511
|
+
shlex.split(sub_args_line)
|
512
|
+
+ [':']
|
513
|
+
+ pipeline_args
|
514
|
+
)
|
meerschaum/_internal/entry.py
CHANGED
@@ -11,6 +11,8 @@ from __future__ import annotations
|
|
11
11
|
|
12
12
|
import os
|
13
13
|
import sys
|
14
|
+
import pathlib
|
15
|
+
|
14
16
|
from meerschaum.utils.typing import SuccessTuple, List, Optional, Dict, Callable, Any
|
15
17
|
from meerschaum.config.static import STATIC_CONFIG as _STATIC_CONFIG
|
16
18
|
|
@@ -19,8 +21,17 @@ if (_STATIC_CONFIG['environment']['systemd_log_path']) in os.environ:
|
|
19
21
|
from meerschaum.utils.daemon import RotatingFile as _RotatingFile, StdinFile as _StdinFile
|
20
22
|
from meerschaum.config import get_config as _get_config
|
21
23
|
|
22
|
-
_systemd_result_path =
|
23
|
-
|
24
|
+
_systemd_result_path = pathlib.Path(
|
25
|
+
os.environ[_STATIC_CONFIG['environment']['systemd_result_path']]
|
26
|
+
)
|
27
|
+
_systemd_log_path = pathlib.Path(
|
28
|
+
os.environ[_STATIC_CONFIG['environment']['systemd_log_path']]
|
29
|
+
)
|
30
|
+
_systemd_delete_job = (
|
31
|
+
(os.environ.get(_STATIC_CONFIG['environment']['systemd_delete_job'], None) or '0')
|
32
|
+
not in (None, '0', 'false')
|
33
|
+
)
|
34
|
+
_job_name = os.environ[_STATIC_CONFIG['environment']['daemon_id']]
|
24
35
|
_systemd_log = _RotatingFile(
|
25
36
|
_systemd_log_path,
|
26
37
|
write_timestamps=True,
|
@@ -51,6 +62,7 @@ def entry(
|
|
51
62
|
split_chained_sysargs,
|
52
63
|
split_pipeline_sysargs,
|
53
64
|
sysargs_has_api_executor_keys,
|
65
|
+
get_pipeline_sysargs,
|
54
66
|
)
|
55
67
|
from meerschaum.config.static import STATIC_CONFIG
|
56
68
|
if sysargs is None:
|
@@ -72,15 +84,7 @@ def entry(
|
|
72
84
|
else split_chained_sysargs(sysargs)
|
73
85
|
)
|
74
86
|
if pipeline_args:
|
75
|
-
|
76
|
-
'sub_args_line': shlex.join(sysargs),
|
77
|
-
'patch_args': _patch_args,
|
78
|
-
}
|
79
|
-
chained_sysargs = [
|
80
|
-
['start', 'pipeline']
|
81
|
-
+ [str(arg) for arg in pipeline_args]
|
82
|
-
+ ['-P', json.dumps(start_pipeline_params, separators=(',', ':'))]
|
83
|
-
]
|
87
|
+
chained_sysargs = [get_pipeline_sysargs(sysargs, pipeline_args, _patch_args=_patch_args)]
|
84
88
|
|
85
89
|
results: List[SuccessTuple] = []
|
86
90
|
|
@@ -169,8 +173,20 @@ def entry(
|
|
169
173
|
|
170
174
|
if _systemd_result_path:
|
171
175
|
import json
|
172
|
-
|
173
|
-
|
176
|
+
from meerschaum.utils.warnings import warn
|
177
|
+
import meerschaum as mrsm
|
178
|
+
|
179
|
+
job = mrsm.Job(_job_name, executor_keys='systemd')
|
180
|
+
if job.delete_after_completion:
|
181
|
+
delete_success, delete_msg = job.delete()
|
182
|
+
mrsm.pprint((delete_success, delete_msg))
|
183
|
+
else:
|
184
|
+
try:
|
185
|
+
if _systemd_result_path.parent.exists():
|
186
|
+
with open(_systemd_result_path, 'w+', encoding='utf-8') as f:
|
187
|
+
json.dump((success, msg), f)
|
188
|
+
except Exception as e:
|
189
|
+
warn(f"Failed to write job result:\n{e}")
|
174
190
|
|
175
191
|
return success, msg
|
176
192
|
|
meerschaum/actions/api.py
CHANGED
@@ -89,22 +89,22 @@ def api(
|
|
89
89
|
return success, message
|
90
90
|
|
91
91
|
def _api_start(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
92
|
+
action: Optional[List[str]] = None,
|
93
|
+
host: Optional[str] = None,
|
94
|
+
port: Optional[int] = None,
|
95
|
+
workers: Optional[int] = None,
|
96
|
+
mrsm_instance: Optional[str] = None,
|
97
|
+
no_dash: bool = False,
|
98
|
+
no_auth: bool = False,
|
99
|
+
private: bool = False,
|
100
|
+
secure: bool = False,
|
101
|
+
debug: bool = False,
|
102
|
+
nopretty: bool = False,
|
103
|
+
production: bool = False,
|
104
|
+
keyfile: Optional[str] = None,
|
105
|
+
certfile: Optional[str] = None,
|
106
|
+
**kw: Any
|
107
|
+
) -> SuccessTuple:
|
108
108
|
"""Start the API server.
|
109
109
|
|
110
110
|
Parameters
|
meerschaum/actions/bootstrap.py
CHANGED
@@ -234,7 +234,13 @@ def _bootstrap_connectors(
|
|
234
234
|
Prompt the user for the details necessary to create a Connector.
|
235
235
|
"""
|
236
236
|
from meerschaum.connectors.parse import is_valid_connector_keys
|
237
|
-
from meerschaum.connectors import
|
237
|
+
from meerschaum.connectors import (
|
238
|
+
connectors,
|
239
|
+
get_connector,
|
240
|
+
types,
|
241
|
+
custom_types,
|
242
|
+
_load_builtin_custom_connectors,
|
243
|
+
)
|
238
244
|
from meerschaum.utils.prompt import prompt, yes_no, choose
|
239
245
|
from meerschaum.config import get_config
|
240
246
|
from meerschaum.config._edit import write_config
|
@@ -246,6 +252,7 @@ def _bootstrap_connectors(
|
|
246
252
|
|
247
253
|
abort_tuple = False, "No connectors bootstrapped."
|
248
254
|
_clear = get_config('shell', 'clear_screen', patch=True)
|
255
|
+
_load_builtin_custom_connectors()
|
249
256
|
|
250
257
|
if action is None:
|
251
258
|
action = []
|
@@ -262,8 +269,8 @@ def _bootstrap_connectors(
|
|
262
269
|
+ ' See https://meerschaum.io/reference/connectors '
|
263
270
|
+ 'for documentation on connectors.\n'
|
264
271
|
),
|
265
|
-
sorted(
|
266
|
-
default
|
272
|
+
sorted([k for k in connectors if k != 'plugin']),
|
273
|
+
default='sql',
|
267
274
|
)
|
268
275
|
except KeyboardInterrupt:
|
269
276
|
return abort_tuple
|
@@ -288,21 +295,30 @@ def _bootstrap_connectors(
|
|
288
295
|
warn(f"Connector '{_type}:{_label}' already exists.", stack=False)
|
289
296
|
overwrite = yes_no(
|
290
297
|
f"Do you want to overwrite connector '{_type}:{_label}'?",
|
291
|
-
default
|
292
|
-
yes
|
293
|
-
noask
|
298
|
+
default='n',
|
299
|
+
yes=yes,
|
300
|
+
noask=noask,
|
294
301
|
)
|
295
302
|
if not overwrite and not force:
|
296
|
-
return False,
|
303
|
+
return False, "No changes made to connector configuration."
|
297
304
|
break
|
298
305
|
elif _label == "":
|
299
|
-
warn(
|
306
|
+
warn("Please enter a label.", stack=False)
|
300
307
|
else:
|
301
308
|
break
|
302
309
|
|
303
310
|
cls = types.get(_type)
|
304
311
|
cls_required_attrs = getattr(cls, 'REQUIRED_ATTRIBUTES', [])
|
305
|
-
|
312
|
+
cls_optional_attrs = getattr(cls, 'OPTIONAL_ATTRIBUTES', [])
|
313
|
+
cls_default_attrs = getattr(cls, 'DEFAULT_ATTRIBUTES', {})
|
314
|
+
type_attributes = connector_attributes.get(
|
315
|
+
_type,
|
316
|
+
{
|
317
|
+
'required': cls_required_attrs,
|
318
|
+
'optional': cls_optional_attrs,
|
319
|
+
'default': cls_default_attrs,
|
320
|
+
}
|
321
|
+
)
|
306
322
|
|
307
323
|
new_attributes = {}
|
308
324
|
if 'flavors' in type_attributes:
|
@@ -323,6 +339,7 @@ def _bootstrap_connectors(
|
|
323
339
|
default = type_attributes['flavors'][flavor].get('defaults', {})
|
324
340
|
else:
|
325
341
|
required = sorted(list(type_attributes.get('required', {})))
|
342
|
+
optional = sorted(list(type_attributes.get('optional', {})))
|
326
343
|
default = type_attributes.get('default', {})
|
327
344
|
info(
|
328
345
|
f"Please answer the following questions to configure the new connector '{_type}:{_label}'."
|
@@ -330,13 +347,22 @@ def _bootstrap_connectors(
|
|
330
347
|
)
|
331
348
|
for r in required:
|
332
349
|
try:
|
333
|
-
|
350
|
+
default_val = str(default.get(r)) if r in default else None
|
351
|
+
val = prompt(f"Value for {r}:", default=default_val)
|
334
352
|
except KeyboardInterrupt:
|
335
353
|
continue
|
336
354
|
if is_int(val):
|
337
355
|
val = int(val)
|
338
356
|
new_attributes[r] = val
|
339
357
|
|
358
|
+
for o in optional:
|
359
|
+
try:
|
360
|
+
val = prompt(f"Value for {o} (optional; empty to omit):")
|
361
|
+
except KeyboardInterrupt:
|
362
|
+
continue
|
363
|
+
if val:
|
364
|
+
new_attributes[o] = val
|
365
|
+
|
340
366
|
for k, v in default.items():
|
341
367
|
### skip already configured attributes, (e.g. flavor or from required)
|
342
368
|
if k in new_attributes:
|
meerschaum/actions/start.py
CHANGED
@@ -89,6 +89,7 @@ def _start_jobs(
|
|
89
89
|
name: Optional[str] = None,
|
90
90
|
sysargs: Optional[List[str]] = None,
|
91
91
|
executor_keys: Optional[str] = None,
|
92
|
+
rm: bool = False,
|
92
93
|
debug: bool = False,
|
93
94
|
**kw
|
94
95
|
) -> SuccessTuple:
|
@@ -210,7 +211,7 @@ def _start_jobs(
|
|
210
211
|
|
211
212
|
def _run_new_job(name: Optional[str] = None):
|
212
213
|
name = name or get_new_daemon_name()
|
213
|
-
job = Job(name, sysargs, executor_keys=executor_keys)
|
214
|
+
job = Job(name, sysargs, executor_keys=executor_keys, delete_after_completion=rm)
|
214
215
|
return job.start(debug=debug), name
|
215
216
|
|
216
217
|
def _run_existing_job(name: str):
|
@@ -454,12 +455,12 @@ def _start_webterm(
|
|
454
455
|
|
455
456
|
|
456
457
|
def _start_connectors(
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
458
|
+
action: Optional[List[str]] = None,
|
459
|
+
connector_keys: Optional[List[str]] = None,
|
460
|
+
min_seconds: int = 3,
|
461
|
+
debug: bool = False,
|
462
|
+
**kw
|
463
|
+
) -> SuccessTuple:
|
463
464
|
"""
|
464
465
|
Start polling connectors to verify a connection can be made.
|
465
466
|
"""
|
@@ -479,7 +480,7 @@ def _start_connectors(
|
|
479
480
|
for keys in unique_keys:
|
480
481
|
try:
|
481
482
|
conn = parse_instance_keys(keys)
|
482
|
-
except Exception
|
483
|
+
except Exception:
|
483
484
|
warn(f"Invalid connector keys: '{keys}'. Skipping...", stack=False)
|
484
485
|
continue
|
485
486
|
valid_conns.append(conn)
|
@@ -487,20 +488,19 @@ def _start_connectors(
|
|
487
488
|
if not valid_conns:
|
488
489
|
return False, "No valid connector keys were provided."
|
489
490
|
|
490
|
-
|
491
491
|
connected = {}
|
492
492
|
def connect(conn):
|
493
493
|
success = retry_connect(
|
494
494
|
conn,
|
495
|
-
retry_wait
|
496
|
-
enforce_chaining
|
497
|
-
enforce_login
|
498
|
-
print_on_connect
|
499
|
-
debug
|
495
|
+
retry_wait=min_seconds,
|
496
|
+
enforce_chaining=False,
|
497
|
+
enforce_login=False,
|
498
|
+
print_on_connect=True,
|
499
|
+
debug=debug,
|
500
500
|
)
|
501
501
|
connected[conn] = success
|
502
502
|
return success
|
503
|
-
|
503
|
+
|
504
504
|
pool = get_pool()
|
505
505
|
try:
|
506
506
|
pool.map(connect, valid_conns)
|
@@ -568,6 +568,7 @@ def _start_pipeline(
|
|
568
568
|
else 1
|
569
569
|
)
|
570
570
|
|
571
|
+
params = params or {}
|
571
572
|
sub_args_line = params.get('sub_args_line', None)
|
572
573
|
patch_args = params.get('patch_args', None)
|
573
574
|
|
meerschaum/api/_events.py
CHANGED
@@ -20,12 +20,14 @@ from meerschaum.connectors.poll import retry_connect
|
|
20
20
|
from meerschaum.utils.warnings import warn
|
21
21
|
from meerschaum._internal.term.tools import is_webterm_running
|
22
22
|
from meerschaum.jobs import (
|
23
|
+
get_jobs,
|
23
24
|
start_check_jobs_thread,
|
24
25
|
stop_check_jobs_thread,
|
25
26
|
get_executor_keys_from_context,
|
26
27
|
)
|
28
|
+
from meerschaum.config.static import STATIC_CONFIG
|
27
29
|
|
28
|
-
|
30
|
+
TEMP_PREFIX: str = STATIC_CONFIG['api']['jobs']['temp_prefix']
|
29
31
|
|
30
32
|
@app.on_event("startup")
|
31
33
|
async def startup():
|
@@ -51,8 +53,7 @@ async def startup():
|
|
51
53
|
await shutdown()
|
52
54
|
os._exit(1)
|
53
55
|
|
54
|
-
|
55
|
-
start_check_jobs_thread()
|
56
|
+
start_check_jobs_thread()
|
56
57
|
|
57
58
|
|
58
59
|
@app.on_event("shutdown")
|
@@ -65,11 +66,14 @@ async def shutdown():
|
|
65
66
|
if get_api_connector().type == 'sql':
|
66
67
|
get_api_connector().engine.dispose()
|
67
68
|
|
68
|
-
|
69
|
-
stop_check_jobs_thread()
|
69
|
+
stop_check_jobs_thread()
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
temp_jobs = {
|
72
|
+
name: job
|
73
|
+
for name, job in get_jobs(include_hidden=True).items()
|
74
|
+
if name.startswith(TEMP_PREFIX)
|
75
|
+
}
|
76
|
+
for job in temp_jobs.values():
|
73
77
|
job.delete()
|
74
78
|
|
75
79
|
### Terminate any running jobs left over.
|
meerschaum/api/dash/__init__.py
CHANGED
@@ -50,16 +50,17 @@ stylesheets = [
|
|
50
50
|
'/static/css/bootstrap.min.css',
|
51
51
|
'/static/css/dbc_dark.css',
|
52
52
|
'/static/css/dash.css',
|
53
|
+
'/static/css/bootstrap-icons/font/bootstrap-icons.min.css',
|
53
54
|
]
|
54
55
|
scripts = ['/static/js/node_modules/xterm/lib/xterm.js']
|
55
56
|
dash_app = enrich.DashProxy(
|
56
57
|
__name__,
|
57
|
-
title
|
58
|
-
requests_pathname_prefix
|
59
|
-
external_stylesheets
|
60
|
-
update_title
|
61
|
-
suppress_callback_exceptions
|
62
|
-
transforms
|
58
|
+
title='Meerschaum Web',
|
59
|
+
requests_pathname_prefix=endpoints['dash'] + '/',
|
60
|
+
external_stylesheets=stylesheets,
|
61
|
+
update_title=None,
|
62
|
+
suppress_callback_exceptions=True,
|
63
|
+
transforms=[
|
63
64
|
enrich.TriggerTransform(),
|
64
65
|
enrich.MultiplexerTransform(),
|
65
66
|
],
|
@@ -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()
|
@@ -101,6 +101,7 @@ _paths = {
|
|
101
101
|
'' : pages.dashboard.layout,
|
102
102
|
'plugins' : pages.plugins.layout,
|
103
103
|
'register': pages.register.layout,
|
104
|
+
'pipes' : pages.pipes.layout,
|
104
105
|
}
|
105
106
|
_required_login = {''}
|
106
107
|
|
@@ -113,10 +114,10 @@ _required_login = {''}
|
|
113
114
|
State('location', 'href'),
|
114
115
|
)
|
115
116
|
def update_page_layout_div(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
117
|
+
pathname: str,
|
118
|
+
session_store_data: Dict[str, Any],
|
119
|
+
location_href: str,
|
120
|
+
) -> Tuple[List[Any], Dict[str, Any]]:
|
120
121
|
"""
|
121
122
|
Route the user to the correct page.
|
122
123
|
|
@@ -135,7 +136,7 @@ def update_page_layout_div(
|
|
135
136
|
ctx = dash.callback_context
|
136
137
|
dash_endpoint = endpoints['dash']
|
137
138
|
try:
|
138
|
-
session_id = session_store_data.get('session-id', None)
|
139
|
+
session_id = session_store_data.get('session-id', None)
|
139
140
|
except AttributeError:
|
140
141
|
session_id = None
|
141
142
|
|
@@ -760,6 +761,7 @@ def update_pipe_accordion(item, session_store_data):
|
|
760
761
|
raise PreventUpdate
|
761
762
|
|
762
763
|
session_id = session_store_data.get('session-id', None)
|
764
|
+
print(f"{session_id=}")
|
763
765
|
authenticated = is_session_authenticated(str(session_id))
|
764
766
|
return accordion_items_from_pipe(pipe, active_items=[item], authenticated=authenticated)
|
765
767
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define callbacks for the `/dash/pipes/` page.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from dash.exceptions import PreventUpdate
|
9
|
+
from dash.dependencies import Input, Output, State
|
10
|
+
from dash import no_update
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
13
|
+
from meerschaum.api.dash import dash_app, debug, active_sessions
|
14
|
+
from meerschaum.api.dash.pipes import build_pipe_card
|
15
|
+
from meerschaum.api import get_api_connector, CHECK_UPDATE
|
16
|
+
from meerschaum.utils.packages import import_html, import_dcc
|
17
|
+
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
18
|
+
|
19
|
+
|
20
|
+
@dash_app.callback(
|
21
|
+
Output('pipe-output-div', 'children'),
|
22
|
+
Input('pipes-location', 'pathname'),
|
23
|
+
)
|
24
|
+
def render_page_from_url(pathname):
|
25
|
+
if not str(pathname).startswith('/dash/pipes'):
|
26
|
+
return no_update
|
27
|
+
|
28
|
+
keys = pathname.replace('/dash/pipes', '').lstrip('/').rstrip('/').split('/')
|
29
|
+
if len(keys) not in (2, 3):
|
30
|
+
return no_update
|
31
|
+
|
32
|
+
ck = keys[0]
|
33
|
+
mk = keys[1]
|
34
|
+
lk = keys[2] if len(keys) == 3 else None
|
35
|
+
|
36
|
+
pipe = mrsm.Pipe(ck, mk, lk)
|
37
|
+
### TODO Check if logged in
|
38
|
+
return [
|
39
|
+
html.Br(),
|
40
|
+
build_pipe_card(pipe, authenticated=False),
|
41
|
+
html.Br(),
|
42
|
+
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Display pipes via a shareable URL.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from meerschaum.api import get_api_connector, CHECK_UPDATE
|
9
|
+
from meerschaum.utils.packages import import_html, import_dcc
|
10
|
+
html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
|
11
|
+
import dash_bootstrap_components as dbc
|
12
|
+
|
13
|
+
layout = dbc.Container([
|
14
|
+
dcc.Location('pipes-location'),
|
15
|
+
html.Div(id='pipe-output-div'),
|
16
|
+
])
|