meerschaum 2.2.5.dev3__py3-none-any.whl → 2.2.6__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/__init__.py +4 -1
- meerschaum/_internal/arguments/_parser.py +13 -2
- meerschaum/_internal/docs/index.py +523 -26
- meerschaum/_internal/term/__init__.py +2 -2
- meerschaum/actions/bootstrap.py +13 -14
- meerschaum/actions/python.py +11 -8
- meerschaum/actions/register.py +130 -32
- meerschaum/actions/show.py +79 -71
- meerschaum/actions/stop.py +11 -11
- meerschaum/api/dash/callbacks/login.py +21 -13
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/routes/_login.py +5 -5
- meerschaum/config/__init__.py +8 -1
- meerschaum/config/_paths.py +20 -2
- meerschaum/config/_version.py +1 -1
- meerschaum/config/paths.py +21 -2
- meerschaum/config/static/__init__.py +1 -0
- meerschaum/connectors/Connector.py +7 -2
- meerschaum/connectors/__init__.py +7 -5
- meerschaum/connectors/api/APIConnector.py +7 -2
- meerschaum/connectors/api/_actions.py +23 -31
- meerschaum/connectors/api/_uri.py +5 -5
- meerschaum/core/Pipe/__init__.py +7 -3
- meerschaum/core/Pipe/_data.py +23 -15
- meerschaum/core/Pipe/_deduplicate.py +1 -1
- meerschaum/core/Pipe/_dtypes.py +5 -0
- meerschaum/core/Pipe/_fetch.py +18 -16
- meerschaum/core/Pipe/_sync.py +20 -15
- meerschaum/plugins/_Plugin.py +6 -6
- meerschaum/plugins/__init__.py +1 -1
- meerschaum/utils/daemon/RotatingFile.py +15 -16
- meerschaum/utils/dataframe.py +12 -4
- meerschaum/utils/debug.py +9 -15
- meerschaum/utils/formatting/__init__.py +13 -12
- meerschaum/utils/misc.py +117 -11
- meerschaum/utils/packages/__init__.py +7 -1
- meerschaum/utils/typing.py +1 -0
- meerschaum/utils/venv/__init__.py +5 -1
- meerschaum/utils/warnings.py +8 -1
- meerschaum/utils/yaml.py +2 -2
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/METADATA +1 -1
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/RECORD +48 -48
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/WHEEL +1 -1
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/LICENSE +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/NOTICE +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/top_level.txt +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.6.dist-info}/zip-safe +0 -0
meerschaum/actions/python.py
CHANGED
@@ -9,14 +9,14 @@ from __future__ import annotations
|
|
9
9
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional
|
10
10
|
|
11
11
|
def python(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
action: Optional[List[str]] = None,
|
13
|
+
sub_args: Optional[List[str]] = None,
|
14
|
+
nopretty: bool = False,
|
15
|
+
noask: bool = False,
|
16
|
+
venv: Optional[str] = None,
|
17
|
+
debug: bool = False,
|
18
|
+
**kw: Any
|
19
|
+
) -> SuccessTuple:
|
20
20
|
"""
|
21
21
|
Launch a virtual environment's Python interpreter with Meerschaum imported.
|
22
22
|
You may pass flags to the Python binary by surrounding each flag with `[]`.
|
@@ -56,6 +56,9 @@ def python(
|
|
56
56
|
if action is None:
|
57
57
|
action = []
|
58
58
|
|
59
|
+
if noask:
|
60
|
+
nopretty = True
|
61
|
+
|
59
62
|
joined_actions = (
|
60
63
|
["import meerschaum as mrsm"]
|
61
64
|
if venv is None and not sub_args
|
meerschaum/actions/register.py
CHANGED
@@ -7,12 +7,13 @@ Register new Pipes. Requires the API to be running.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
+
import meerschaum as mrsm
|
10
11
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Dict
|
11
12
|
|
12
13
|
def register(
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
action: Optional[List[str]] = None,
|
15
|
+
**kw: Any
|
16
|
+
) -> SuccessTuple:
|
16
17
|
"""
|
17
18
|
Register new items (pipes, plugins, users).
|
18
19
|
|
@@ -23,22 +24,25 @@ def register(
|
|
23
24
|
'pipes' : _register_pipes,
|
24
25
|
'plugins' : _register_plugins,
|
25
26
|
'users' : _register_users,
|
27
|
+
'connectors': _register_connectors,
|
26
28
|
}
|
27
29
|
return choose_subaction(action, options, **kw)
|
28
30
|
|
29
31
|
|
30
32
|
def _complete_register(
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
action: Optional[List[str]] = None,
|
34
|
+
**kw: Any
|
35
|
+
) -> List[str]:
|
34
36
|
"""
|
35
37
|
Override the default Meerschaum `complete_` function.
|
36
38
|
"""
|
37
39
|
if action is None:
|
38
40
|
action = []
|
39
41
|
options = {
|
40
|
-
'plugin'
|
41
|
-
'plugins'
|
42
|
+
'plugin': _complete_register_plugins,
|
43
|
+
'plugins': _complete_register_plugins,
|
44
|
+
'connector': _complete_register_connectors,
|
45
|
+
'connectors': _complete_register_connectors,
|
42
46
|
}
|
43
47
|
|
44
48
|
if len(action) > 0 and action[0] in options:
|
@@ -51,14 +55,14 @@ def _complete_register(
|
|
51
55
|
|
52
56
|
|
53
57
|
def _register_pipes(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
connector_keys: Optional[List[str]] = None,
|
59
|
+
metric_keys: Optional[List[str]] = None,
|
60
|
+
location_keys: Optional[List[str]] = None,
|
61
|
+
params: Optional[Dict[str, Any]] = None,
|
62
|
+
tags: Optional[List[str]] = None,
|
63
|
+
debug: bool = False,
|
64
|
+
**kw: Any
|
65
|
+
) -> SuccessTuple:
|
62
66
|
"""
|
63
67
|
Create and register Pipe objects.
|
64
68
|
|
@@ -147,15 +151,18 @@ def _register_pipes(
|
|
147
151
|
|
148
152
|
|
149
153
|
def _register_plugins(
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
154
|
+
action: Optional[List[str]] = None,
|
155
|
+
repository: Optional[str] = None,
|
156
|
+
shell: bool = False,
|
157
|
+
debug: bool = False,
|
158
|
+
yes: bool = False,
|
159
|
+
noask: bool = False,
|
160
|
+
force: bool = False,
|
161
|
+
**kw: Any
|
162
|
+
) -> SuccessTuple:
|
163
|
+
"""
|
164
|
+
Upload plugins to an API instance (repository).
|
165
|
+
"""
|
159
166
|
from meerschaum.utils.debug import dprint
|
160
167
|
from meerschaum.plugins import reload_plugins, get_plugins_names
|
161
168
|
from meerschaum.connectors.parse import parse_repo_keys
|
@@ -246,17 +253,19 @@ def _register_plugins(
|
|
246
253
|
reload_plugins(debug=debug)
|
247
254
|
return total_success > 0, msg
|
248
255
|
|
256
|
+
|
249
257
|
def _complete_register_plugins(*args, **kw):
|
250
258
|
from meerschaum.actions.uninstall import _complete_uninstall_plugins
|
251
259
|
return _complete_uninstall_plugins(*args, **kw)
|
252
260
|
|
261
|
+
|
253
262
|
def _register_users(
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
263
|
+
action: Optional[List[str]] = None,
|
264
|
+
mrsm_instance: Optional[str] = None,
|
265
|
+
shell: bool = False,
|
266
|
+
debug: bool = False,
|
267
|
+
**kw: Any
|
268
|
+
) -> SuccessTuple:
|
260
269
|
"""
|
261
270
|
Register a new user to a Meerschaum instance.
|
262
271
|
"""
|
@@ -294,7 +303,7 @@ def _register_users(
|
|
294
303
|
nonregistered_users.append(user)
|
295
304
|
|
296
305
|
### prompt for passwords and emails, then try to register
|
297
|
-
success =
|
306
|
+
success = {}
|
298
307
|
successfully_registered_users = set()
|
299
308
|
for _user in nonregistered_users:
|
300
309
|
try:
|
@@ -337,6 +346,95 @@ def _register_users(
|
|
337
346
|
)
|
338
347
|
return succeeded > 0, msg
|
339
348
|
|
349
|
+
|
350
|
+
def _register_connectors(
|
351
|
+
action: Optional[List[str]] = None,
|
352
|
+
connector_keys: Optional[List[str]] = None,
|
353
|
+
params: Optional[Dict[str, Any]] = None,
|
354
|
+
**kwargs: Any
|
355
|
+
) -> SuccessTuple:
|
356
|
+
"""
|
357
|
+
Create new connectors programmatically with `--params`.
|
358
|
+
See `bootstrap connector`.
|
359
|
+
|
360
|
+
Examples:
|
361
|
+
|
362
|
+
mrsm register connector sql:tmp --params 'uri:sqlite:////tmp/tmp.db'
|
363
|
+
|
364
|
+
mrsm register connector -c sql:new --params '{"database": "/tmp/new.db"}'
|
365
|
+
"""
|
366
|
+
from meerschaum.config import get_config, write_config
|
367
|
+
from meerschaum.utils.prompt import yes_no
|
368
|
+
from meerschaum.utils.warnings import warn
|
369
|
+
all_keys = (action or []) + (connector_keys or [])
|
370
|
+
if len(all_keys) != 1:
|
371
|
+
return (
|
372
|
+
False,
|
373
|
+
"Provide one pair of keys for the connector to be registered."
|
374
|
+
)
|
375
|
+
|
376
|
+
keys = all_keys[0]
|
377
|
+
|
378
|
+
if keys.count(':') != 1:
|
379
|
+
return False, "Connector keys must be in the format `type:label`."
|
380
|
+
|
381
|
+
type_, label = keys.split(':', maxsplit=1)
|
382
|
+
mrsm_config = get_config('meerschaum')
|
383
|
+
if 'connectors' not in mrsm_config:
|
384
|
+
mrsm_config['connectors'] = {}
|
385
|
+
|
386
|
+
if type_ not in mrsm_config['connectors']:
|
387
|
+
mrsm_config['connectors'] = {}
|
388
|
+
|
389
|
+
is_new = True
|
390
|
+
if label in mrsm_config['connectors'][type_]:
|
391
|
+
rich_table, rich_json, rich_box = mrsm.attempt_import(
|
392
|
+
'rich.table',
|
393
|
+
'rich.json',
|
394
|
+
'rich.box',
|
395
|
+
)
|
396
|
+
existing_params = mrsm_config['connectors'][type_][label]
|
397
|
+
if existing_params == params:
|
398
|
+
return True, "Connector exists, nothing to do."
|
399
|
+
|
400
|
+
table = rich_table.Table(box=rich_box.MINIMAL)
|
401
|
+
table.add_column('Existing Parameters')
|
402
|
+
table.add_column('New Parameters')
|
403
|
+
table.add_row(
|
404
|
+
rich_json.JSON.from_data(existing_params),
|
405
|
+
rich_json.JSON.from_data(params or {}),
|
406
|
+
)
|
407
|
+
|
408
|
+
mrsm.pprint(table)
|
409
|
+
warn(f"Connector '{keys}' already exists.", stack=False)
|
410
|
+
if not yes_no(
|
411
|
+
f"Do you want to overwrite connector '{keys}'?",
|
412
|
+
default='n',
|
413
|
+
**kwargs
|
414
|
+
):
|
415
|
+
return False, "Nothing was changed."
|
416
|
+
|
417
|
+
is_new = False
|
418
|
+
|
419
|
+
mrsm_config['connectors'][type_][label] = params
|
420
|
+
if not write_config({'meerschaum': mrsm_config}):
|
421
|
+
return False, "Failed to update configuration."
|
422
|
+
|
423
|
+
msg = (
|
424
|
+
"Successfully "
|
425
|
+
+ ("registered" if is_new else "updated")
|
426
|
+
+ f" connector '{keys}'."
|
427
|
+
)
|
428
|
+
return True, msg
|
429
|
+
|
430
|
+
|
431
|
+
def _complete_register_connectors(
|
432
|
+
action: Optional[List[str]] = None, **kw: Any
|
433
|
+
) -> List[str]:
|
434
|
+
from meerschaum.actions.show import _complete_show_connectors
|
435
|
+
return _complete_show_connectors(action)
|
436
|
+
|
437
|
+
|
340
438
|
### NOTE: This must be the final statement of the module.
|
341
439
|
### Any subactions added below these lines will not
|
342
440
|
### be added to the `help` docstring.
|
meerschaum/actions/show.py
CHANGED
@@ -48,9 +48,9 @@ def show(
|
|
48
48
|
|
49
49
|
|
50
50
|
def _complete_show(
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
action: Optional[List[str]] = None,
|
52
|
+
**kw: Any
|
53
|
+
) -> List[str]:
|
54
54
|
"""
|
55
55
|
Override the default Meerschaum `complete_` function.
|
56
56
|
"""
|
@@ -91,7 +91,13 @@ def _show_actions(**kw: Any) -> SuccessTuple:
|
|
91
91
|
from meerschaum.utils.misc import print_options
|
92
92
|
from meerschaum._internal.shell.Shell import hidden_commands
|
93
93
|
_actions = [ _a for _a in actions if _a not in hidden_commands ]
|
94
|
-
print_options(
|
94
|
+
print_options(
|
95
|
+
options=_actions,
|
96
|
+
name='actions',
|
97
|
+
actions=False,
|
98
|
+
sort_options=True,
|
99
|
+
**kw
|
100
|
+
)
|
95
101
|
return True, "Success"
|
96
102
|
|
97
103
|
|
@@ -247,16 +253,16 @@ def _show_connectors(
|
|
247
253
|
|
248
254
|
|
249
255
|
def _complete_show_connectors(
|
250
|
-
|
251
|
-
|
256
|
+
action: Optional[List[str]] = None, **kw: Any
|
257
|
+
) -> List[str]:
|
252
258
|
from meerschaum.utils.misc import get_connector_labels
|
253
259
|
_text = action[0] if action else ""
|
254
260
|
return get_connector_labels(search_term=_text, ignore_exact_match=True)
|
255
261
|
|
256
262
|
|
257
263
|
def _show_arguments(
|
258
|
-
|
259
|
-
|
264
|
+
**kw: Any
|
265
|
+
) -> SuccessTuple:
|
260
266
|
"""
|
261
267
|
Show the parsed keyword arguments.
|
262
268
|
"""
|
@@ -266,16 +272,16 @@ def _show_arguments(
|
|
266
272
|
|
267
273
|
|
268
274
|
def _show_data(
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
275
|
+
action: Optional[List[str]] = None,
|
276
|
+
gui: bool = False,
|
277
|
+
begin: Optional[datetime.datetime] = None,
|
278
|
+
end: Optional[datetime.datetime] = None,
|
279
|
+
params: Optional[Dict[str, Any]] = None,
|
280
|
+
chunksize: Optional[int] = -1,
|
281
|
+
nopretty: bool = False,
|
282
|
+
debug: bool = False,
|
283
|
+
**kw: Any
|
284
|
+
) -> SuccessTuple:
|
279
285
|
"""
|
280
286
|
Show pipes data as Pandas DataFrames.
|
281
287
|
|
@@ -374,11 +380,11 @@ def _show_data(
|
|
374
380
|
|
375
381
|
|
376
382
|
def _show_columns(
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
383
|
+
action: Optional[List[str]] = None,
|
384
|
+
debug: bool = False,
|
385
|
+
nopretty: bool = False,
|
386
|
+
**kw: Any
|
387
|
+
) -> SuccessTuple:
|
382
388
|
"""
|
383
389
|
Show the registered and table columns for pipes.
|
384
390
|
"""
|
@@ -392,11 +398,11 @@ def _show_columns(
|
|
392
398
|
|
393
399
|
|
394
400
|
def _show_rowcounts(
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
401
|
+
action: Optional[List[str]] = None,
|
402
|
+
workers: Optional[int] = None,
|
403
|
+
debug: bool = False,
|
404
|
+
**kw: Any
|
405
|
+
) -> SuccessTuple:
|
400
406
|
"""
|
401
407
|
Show the rowcounts for pipes.
|
402
408
|
|
@@ -433,12 +439,12 @@ def _show_rowcounts(
|
|
433
439
|
return True, "Success"
|
434
440
|
|
435
441
|
def _show_plugins(
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
+
action: Optional[List[str]] = None,
|
443
|
+
repository: Optional[str] = None,
|
444
|
+
nopretty: bool = False,
|
445
|
+
debug: bool = False,
|
446
|
+
**kw: Any
|
447
|
+
) -> SuccessTuple:
|
442
448
|
"""
|
443
449
|
Show the installed plugins.
|
444
450
|
"""
|
@@ -475,10 +481,10 @@ def _show_plugins(
|
|
475
481
|
return True, "Success"
|
476
482
|
|
477
483
|
def _show_users(
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
484
|
+
mrsm_instance: Optional[str] = None,
|
485
|
+
debug: bool = False,
|
486
|
+
**kw: Any
|
487
|
+
) -> SuccessTuple:
|
482
488
|
"""
|
483
489
|
Show the registered users in a Meerschaum instance (default is the current instance).
|
484
490
|
"""
|
@@ -498,10 +504,10 @@ def _show_users(
|
|
498
504
|
return True, "Success"
|
499
505
|
|
500
506
|
def _show_packages(
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
507
|
+
action: Optional[List[str]] = None,
|
508
|
+
nopretty: bool = False,
|
509
|
+
**kw: Any
|
510
|
+
) -> SuccessTuple:
|
505
511
|
"""
|
506
512
|
Show the packages in dependency groups, or as a list with `--nopretty`.
|
507
513
|
"""
|
@@ -530,9 +536,9 @@ def _show_packages(
|
|
530
536
|
return True, "Success"
|
531
537
|
|
532
538
|
def _complete_show_packages(
|
533
|
-
|
534
|
-
|
535
|
-
|
539
|
+
action: Optional[List[str]] = None,
|
540
|
+
**kw: Any
|
541
|
+
) -> List[str]:
|
536
542
|
from meerschaum.utils.packages import packages
|
537
543
|
if not action:
|
538
544
|
return sorted(list(packages.keys()))
|
@@ -545,10 +551,10 @@ def _complete_show_packages(
|
|
545
551
|
return possibilities
|
546
552
|
|
547
553
|
def _show_jobs(
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
554
|
+
action: Optional[List[str]] = None,
|
555
|
+
nopretty: bool = False,
|
556
|
+
**kw: Any
|
557
|
+
) -> SuccessTuple:
|
552
558
|
"""
|
553
559
|
Show the currently running and stopped jobs.
|
554
560
|
"""
|
@@ -572,10 +578,10 @@ def _show_jobs(
|
|
572
578
|
|
573
579
|
|
574
580
|
def _show_logs(
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
581
|
+
action: Optional[List[str]] = None,
|
582
|
+
nopretty: bool = False,
|
583
|
+
**kw
|
584
|
+
) -> SuccessTuple:
|
579
585
|
"""
|
580
586
|
Show the logs for jobs.
|
581
587
|
|
@@ -607,13 +613,15 @@ def _show_logs(
|
|
607
613
|
now_follow_str = now.strftime(follow_timestamp_format)
|
608
614
|
|
609
615
|
def build_buffer_spaces(daemons) -> Dict[str, str]:
|
610
|
-
max_len_id =
|
616
|
+
max_len_id = (
|
617
|
+
max(len(d.daemon_id) for d in daemons) + 1
|
618
|
+
) if daemons else 0
|
611
619
|
buffer_len = max(
|
612
620
|
get_config('jobs', 'logs', 'min_buffer_len'),
|
613
|
-
max_len_id
|
621
|
+
max_len_id
|
614
622
|
)
|
615
623
|
return {
|
616
|
-
d.daemon_id: ''.join([' '
|
624
|
+
d.daemon_id: ''.join([' '] * (buffer_len - len(d.daemon_id)))
|
617
625
|
for d in daemons
|
618
626
|
}
|
619
627
|
|
@@ -763,9 +771,9 @@ def _show_logs(
|
|
763
771
|
|
764
772
|
|
765
773
|
def _show_environment(
|
766
|
-
|
767
|
-
|
768
|
-
|
774
|
+
nopretty: bool = False,
|
775
|
+
**kw
|
776
|
+
) -> SuccessTuple:
|
769
777
|
"""
|
770
778
|
Show all of the current environment variables with begin with `'MRSM_'`.
|
771
779
|
"""
|
@@ -783,12 +791,12 @@ def _show_environment(
|
|
783
791
|
|
784
792
|
|
785
793
|
def _show_tags(
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
794
|
+
action: Optional[List[str]] = None,
|
795
|
+
tags: Optional[List[str]] = None,
|
796
|
+
workers: Optional[int] = None,
|
797
|
+
nopretty: bool = False,
|
798
|
+
**kwargs
|
799
|
+
) -> SuccessTuple:
|
792
800
|
"""
|
793
801
|
Show the existing tags and their associated pipes.
|
794
802
|
"""
|
@@ -863,10 +871,10 @@ def _show_tags(
|
|
863
871
|
|
864
872
|
|
865
873
|
def _show_schedules(
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
874
|
+
action: Optional[List[str]] = None,
|
875
|
+
nopretty: bool = False,
|
876
|
+
**kwargs: Any
|
877
|
+
) -> SuccessTuple:
|
870
878
|
"""
|
871
879
|
Print the upcoming timestamps according to the given schedule.
|
872
880
|
|
@@ -914,8 +922,8 @@ def _show_schedules(
|
|
914
922
|
|
915
923
|
|
916
924
|
def _show_venvs(
|
917
|
-
|
918
|
-
|
925
|
+
**kwargs: Any
|
926
|
+
):
|
919
927
|
"""
|
920
928
|
Print the available virtual environments in the current MRSM_ROOT_DIR.
|
921
929
|
"""
|
meerschaum/actions/stop.py
CHANGED
@@ -21,9 +21,9 @@ def stop(action: Optional[List[str]] = None, **kw) -> SuccessTuple:
|
|
21
21
|
|
22
22
|
|
23
23
|
def _complete_stop(
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
action: Optional[List[str]] = None,
|
25
|
+
**kw: Any
|
26
|
+
) -> List[str]:
|
27
27
|
"""
|
28
28
|
Override the default Meerschaum `complete_` function.
|
29
29
|
"""
|
@@ -49,14 +49,14 @@ def _complete_stop(
|
|
49
49
|
|
50
50
|
|
51
51
|
def _stop_jobs(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
52
|
+
action: Optional[List[str]] = None,
|
53
|
+
timeout_seconds: Optional[int] = None,
|
54
|
+
noask: bool = False,
|
55
|
+
force: bool = False,
|
56
|
+
yes: bool = False,
|
57
|
+
nopretty: bool = False,
|
58
|
+
**kw
|
59
|
+
) -> SuccessTuple:
|
60
60
|
"""
|
61
61
|
Stop running jobs that were started with `-d` or `start job`.
|
62
62
|
|
@@ -17,6 +17,7 @@ from dash.dependencies import Input, Output, State
|
|
17
17
|
from meerschaum.api.dash import dash_app, debug, pipes, _get_pipes, active_sessions
|
18
18
|
from meerschaum.api.dash.connectors import get_web_connector
|
19
19
|
from meerschaum.api.routes._login import login
|
20
|
+
from meerschaum.api.dash.components import alert_from_success_tuple
|
20
21
|
from fastapi_login.exceptions import InvalidCredentialsException
|
21
22
|
from fastapi.exceptions import HTTPException
|
22
23
|
dbc = attempt_import('dash_bootstrap_components', lazy=False, check_update=CHECK_UPDATE)
|
@@ -39,6 +40,7 @@ def show_registration_disabled_collapse(n_clicks, is_open):
|
|
39
40
|
Output('session-store', 'data'),
|
40
41
|
Output('username-input', 'className'),
|
41
42
|
Output('location', 'pathname'),
|
43
|
+
Output('login-alert-div', 'children'),
|
42
44
|
Input('username-input', 'n_submit'),
|
43
45
|
Input('password-input', 'n_submit'),
|
44
46
|
Input('login-button', 'n_clicks'),
|
@@ -48,14 +50,14 @@ def show_registration_disabled_collapse(n_clicks, is_open):
|
|
48
50
|
State('location', 'pathname'),
|
49
51
|
)
|
50
52
|
def login_button_click(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
username_submit,
|
54
|
+
password_submit,
|
55
|
+
n_clicks,
|
56
|
+
username,
|
57
|
+
password,
|
58
|
+
location_href,
|
59
|
+
location_pathname,
|
60
|
+
):
|
59
61
|
"""
|
60
62
|
When the user submits the login form, check the login.
|
61
63
|
On successful login, set the session id.
|
@@ -63,12 +65,18 @@ def login_button_click(
|
|
63
65
|
form_class = 'form-control'
|
64
66
|
ctx = dash.callback_context
|
65
67
|
if not username or not password or not ctx.triggered:
|
66
|
-
|
68
|
+
raise PreventUpdate
|
69
|
+
|
67
70
|
try:
|
68
|
-
|
69
|
-
session_data = {
|
71
|
+
_ = login({'username': username, 'password': password})
|
72
|
+
session_data = {
|
73
|
+
'session-id': str(uuid.uuid4()),
|
74
|
+
'location.href': location_href,
|
75
|
+
}
|
70
76
|
active_sessions[session_data['session-id']] = {'username': username}
|
77
|
+
alerts = []
|
71
78
|
except HTTPException:
|
72
79
|
form_class += ' is-invalid'
|
73
|
-
session_data =
|
74
|
-
|
80
|
+
session_data = dash.no_update
|
81
|
+
alerts = alert_from_success_tuple((False, "Invalid login."))
|
82
|
+
return session_data, form_class, dash.no_update, alerts
|
@@ -31,7 +31,7 @@ registration_div = html.Div(
|
|
31
31
|
else [
|
32
32
|
dcc.Markdown("""
|
33
33
|
#### **Web registration is disabled for security.**
|
34
|
-
You can
|
34
|
+
You can register users via the CLI with `mrsm register user`.
|
35
35
|
"""),
|
36
36
|
dbc.Button(
|
37
37
|
'More information.',
|
@@ -80,6 +80,7 @@ layout = dbc.Container([
|
|
80
80
|
html.Br(),
|
81
81
|
dbc.Container([
|
82
82
|
dcc.Location(id='location-login', refresh=True),
|
83
|
+
html.Div(id="login-alert-div"),
|
83
84
|
html.Div([
|
84
85
|
dbc.Container(
|
85
86
|
html.Img(
|
@@ -129,4 +130,3 @@ layout = dbc.Container([
|
|
129
130
|
]),
|
130
131
|
], className='jumbotron')
|
131
132
|
])
|
132
|
-
|
meerschaum/api/routes/_login.py
CHANGED
@@ -32,16 +32,16 @@ def load_user(
|
|
32
32
|
|
33
33
|
|
34
34
|
@app.post(endpoints['login'], tags=['Users'])
|
35
|
-
|
35
|
+
def login(
|
36
36
|
data: CustomOAuth2PasswordRequestForm = fastapi.Depends()
|
37
|
-
# data: dict[str, str],
|
38
|
-
# request: Request
|
39
37
|
) -> Dict[str, Any]:
|
40
38
|
"""
|
41
39
|
Login and set the session token.
|
42
40
|
"""
|
43
41
|
username, password = (
|
44
|
-
(data
|
42
|
+
(data['username'], data['password'])
|
43
|
+
if isinstance(data, dict)
|
44
|
+
else (data.username, data.password)
|
45
45
|
) if not no_auth else ('no-auth', 'no-auth')
|
46
46
|
|
47
47
|
user = User(username, password)
|
@@ -62,7 +62,7 @@ async def login(
|
|
62
62
|
return {
|
63
63
|
'access_token': access_token,
|
64
64
|
'token_type': 'bearer',
|
65
|
-
'expires'
|
65
|
+
'expires': expires_dt,
|
66
66
|
}
|
67
67
|
|
68
68
|
|