meerschaum 2.9.4__py3-none-any.whl → 3.0.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/__init__.py +5 -2
- meerschaum/_internal/__init__.py +1 -0
- meerschaum/_internal/arguments/_parse_arguments.py +4 -4
- meerschaum/_internal/arguments/_parser.py +33 -4
- meerschaum/_internal/cli/__init__.py +6 -0
- meerschaum/_internal/cli/daemons.py +103 -0
- meerschaum/_internal/cli/entry.py +220 -0
- meerschaum/_internal/cli/workers.py +435 -0
- meerschaum/_internal/docs/index.py +48 -2
- meerschaum/_internal/entry.py +50 -14
- meerschaum/_internal/shell/Shell.py +121 -29
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +359 -0
- meerschaum/_internal/term/TermPageHandler.py +1 -2
- meerschaum/_internal/term/__init__.py +40 -6
- meerschaum/_internal/term/tools.py +33 -8
- meerschaum/actions/__init__.py +6 -4
- meerschaum/actions/api.py +53 -13
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/bootstrap.py +8 -8
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +171 -25
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +143 -6
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +184 -31
- meerschaum/actions/start.py +166 -17
- meerschaum/actions/stop.py +38 -2
- meerschaum/actions/sync.py +7 -2
- meerschaum/actions/tag.py +9 -8
- meerschaum/actions/verify.py +5 -8
- meerschaum/api/__init__.py +45 -15
- meerschaum/api/_events.py +46 -4
- meerschaum/api/_oauth2.py +162 -9
- meerschaum/api/_tokens.py +102 -0
- meerschaum/api/dash/__init__.py +0 -3
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/custom.py +4 -3
- meerschaum/api/dash/callbacks/dashboard.py +228 -117
- meerschaum/api/dash/callbacks/jobs.py +14 -7
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +194 -14
- meerschaum/api/dash/callbacks/plugins.py +0 -1
- meerschaum/api/dash/callbacks/register.py +10 -3
- meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
- meerschaum/api/dash/callbacks/tokens.py +389 -0
- meerschaum/api/dash/components.py +36 -15
- meerschaum/api/dash/jobs.py +1 -1
- meerschaum/api/dash/keys.py +35 -93
- meerschaum/api/dash/pages/__init__.py +2 -1
- meerschaum/api/dash/pages/dashboard.py +1 -20
- meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +16 -5
- meerschaum/api/dash/pages/settings/password_reset.py +1 -1
- meerschaum/api/dash/pages/tokens.py +53 -0
- meerschaum/api/dash/pipes.py +438 -88
- meerschaum/api/dash/sessions.py +12 -0
- meerschaum/api/dash/tokens.py +603 -0
- meerschaum/api/dash/websockets.py +1 -1
- meerschaum/api/dash/webterm.py +18 -6
- meerschaum/api/models/__init__.py +23 -3
- meerschaum/api/models/_actions.py +22 -0
- meerschaum/api/models/_pipes.py +91 -7
- meerschaum/api/models/_tokens.py +81 -0
- meerschaum/api/resources/static/css/dash.css +16 -0
- meerschaum/api/resources/static/js/terminado.js +3 -0
- meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
- meerschaum/api/resources/templates/termpage.html +13 -0
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +3 -4
- meerschaum/api/routes/_connectors.py +3 -7
- meerschaum/api/routes/_jobs.py +26 -35
- meerschaum/api/routes/_login.py +120 -15
- meerschaum/api/routes/_misc.py +5 -10
- meerschaum/api/routes/_pipes.py +178 -143
- meerschaum/api/routes/_plugins.py +38 -28
- meerschaum/api/routes/_tokens.py +236 -0
- meerschaum/api/routes/_users.py +47 -35
- meerschaum/api/routes/_version.py +3 -3
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +100 -30
- meerschaum/config/_default.py +132 -64
- meerschaum/config/_edit.py +38 -32
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +10 -8
- meerschaum/config/_paths.py +133 -13
- meerschaum/config/_read_config.py +87 -36
- meerschaum/config/_sync.py +6 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +37 -15
- meerschaum/config/static.py +18 -0
- meerschaum/connectors/_Connector.py +11 -6
- meerschaum/connectors/__init__.py +41 -22
- meerschaum/connectors/api/_APIConnector.py +34 -6
- meerschaum/connectors/api/_actions.py +2 -2
- meerschaum/connectors/api/_jobs.py +12 -1
- meerschaum/connectors/api/_login.py +33 -7
- meerschaum/connectors/api/_misc.py +2 -2
- meerschaum/connectors/api/_pipes.py +23 -32
- meerschaum/connectors/api/_plugins.py +2 -2
- meerschaum/connectors/api/_request.py +1 -1
- meerschaum/connectors/api/_tokens.py +146 -0
- meerschaum/connectors/api/_users.py +70 -58
- meerschaum/connectors/instance/_InstanceConnector.py +83 -0
- meerschaum/connectors/instance/__init__.py +10 -0
- meerschaum/connectors/instance/_pipes.py +442 -0
- meerschaum/connectors/instance/_plugins.py +159 -0
- meerschaum/connectors/instance/_tokens.py +317 -0
- meerschaum/connectors/instance/_users.py +188 -0
- meerschaum/connectors/parse.py +5 -2
- meerschaum/connectors/sql/_SQLConnector.py +22 -5
- meerschaum/connectors/sql/_cli.py +12 -11
- meerschaum/connectors/sql/_create_engine.py +12 -168
- meerschaum/connectors/sql/_fetch.py +2 -18
- meerschaum/connectors/sql/_pipes.py +295 -278
- meerschaum/connectors/sql/_plugins.py +29 -0
- meerschaum/connectors/sql/_sql.py +47 -22
- meerschaum/connectors/sql/_users.py +36 -2
- meerschaum/connectors/sql/tables/__init__.py +254 -122
- meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
- meerschaum/connectors/valkey/_pipes.py +60 -31
- meerschaum/connectors/valkey/_plugins.py +2 -26
- meerschaum/core/Pipe/__init__.py +115 -85
- meerschaum/core/Pipe/_attributes.py +425 -124
- meerschaum/core/Pipe/_bootstrap.py +54 -24
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +96 -68
- meerschaum/core/Pipe/_deduplicate.py +0 -13
- meerschaum/core/Pipe/_delete.py +12 -21
- meerschaum/core/Pipe/_drop.py +11 -23
- meerschaum/core/Pipe/_dtypes.py +49 -19
- meerschaum/core/Pipe/_edit.py +14 -4
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_show.py +5 -5
- meerschaum/core/Pipe/_sync.py +123 -204
- meerschaum/core/Pipe/_verify.py +4 -4
- meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
- meerschaum/core/Plugin/__init__.py +1 -1
- meerschaum/core/Token/_Token.py +220 -0
- meerschaum/core/Token/__init__.py +12 -0
- meerschaum/core/User/_User.py +35 -10
- meerschaum/core/User/__init__.py +9 -1
- meerschaum/core/__init__.py +1 -0
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +149 -38
- meerschaum/jobs/__init__.py +3 -2
- meerschaum/jobs/systemd.py +8 -3
- meerschaum/models/__init__.py +35 -0
- meerschaum/models/pipes.py +247 -0
- meerschaum/models/tokens.py +38 -0
- meerschaum/models/users.py +26 -0
- meerschaum/plugins/__init__.py +301 -88
- meerschaum/plugins/bootstrap.py +510 -4
- meerschaum/utils/_get_pipes.py +97 -30
- meerschaum/utils/daemon/Daemon.py +199 -43
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
- meerschaum/utils/daemon/RotatingFile.py +63 -36
- meerschaum/utils/daemon/StdinFile.py +53 -13
- meerschaum/utils/daemon/__init__.py +47 -6
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/dataframe.py +480 -82
- meerschaum/utils/debug.py +49 -19
- meerschaum/utils/dtypes/__init__.py +478 -37
- meerschaum/utils/dtypes/sql.py +369 -29
- meerschaum/utils/formatting/__init__.py +5 -2
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +52 -50
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +44 -18
- meerschaum/utils/misc.py +268 -186
- meerschaum/utils/packages/__init__.py +25 -40
- meerschaum/utils/packages/_packages.py +42 -34
- meerschaum/utils/pipes.py +213 -0
- meerschaum/utils/process.py +2 -2
- meerschaum/utils/prompt.py +175 -144
- meerschaum/utils/schedule.py +2 -1
- meerschaum/utils/sql.py +135 -49
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/typing.py +1 -4
- meerschaum/utils/venv/_Venv.py +2 -2
- meerschaum/utils/venv/__init__.py +7 -7
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
- meerschaum-3.0.0.dist-info/RECORD +289 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
- meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
- meerschaum/api/models/_interfaces.py +0 -15
- meerschaum/api/models/_locations.py +0 -15
- meerschaum/api/models/_metrics.py +0 -15
- meerschaum/config/_environment.py +0 -145
- meerschaum/config/static/__init__.py +0 -186
- meerschaum-2.9.4.dist-info/RECORD +0 -263
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
meerschaum/actions/register.py
CHANGED
@@ -7,6 +7,9 @@ Register new Pipes. Requires the API to be running.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
+
|
11
|
+
from datetime import datetime, timedelta, timezone
|
12
|
+
|
10
13
|
import meerschaum as mrsm
|
11
14
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Dict
|
12
15
|
|
@@ -26,6 +29,7 @@ def register(
|
|
26
29
|
'plugins' : _register_plugins,
|
27
30
|
'users' : _register_users,
|
28
31
|
'connectors': _register_connectors,
|
32
|
+
'tokens' : _register_tokens,
|
29
33
|
}
|
30
34
|
return choose_subaction(action, options, **kw)
|
31
35
|
|
@@ -175,11 +179,11 @@ def _register_plugins(
|
|
175
179
|
reload_plugins(debug=debug)
|
176
180
|
|
177
181
|
repo_connector = parse_repo_keys(repository)
|
178
|
-
if repo_connector.
|
182
|
+
if repo_connector.type != 'api':
|
179
183
|
return False, (
|
180
184
|
"Can only upload plugins to the Meerschaum API." +
|
181
|
-
f"Connector '{repo_connector}' is
|
182
|
-
f"'{
|
185
|
+
f"Connector '{repo_connector}' is " +
|
186
|
+
f"'{type(repo_connector)}'."
|
183
187
|
)
|
184
188
|
|
185
189
|
if len(action) == 0 or action == ['']:
|
@@ -272,6 +276,7 @@ def _complete_register_plugins(*args, **kw):
|
|
272
276
|
def _register_users(
|
273
277
|
action: Optional[List[str]] = None,
|
274
278
|
mrsm_instance: Optional[str] = None,
|
279
|
+
scopes: Optional[List[str]] = None,
|
275
280
|
shell: bool = False,
|
276
281
|
debug: bool = False,
|
277
282
|
**kw: Any
|
@@ -280,7 +285,7 @@ def _register_users(
|
|
280
285
|
Register a new user to a Meerschaum instance.
|
281
286
|
"""
|
282
287
|
from meerschaum.config import get_config
|
283
|
-
from meerschaum.
|
288
|
+
from meerschaum._internal.static import STATIC_CONFIG
|
284
289
|
from meerschaum.connectors.parse import parse_instance_keys
|
285
290
|
from meerschaum.utils.warnings import warn, info
|
286
291
|
from meerschaum.core import User
|
@@ -333,9 +338,17 @@ def _register_users(
|
|
333
338
|
)
|
334
339
|
if len(email) == 0:
|
335
340
|
email = None
|
336
|
-
user = User(
|
341
|
+
user = User(
|
342
|
+
username,
|
343
|
+
password,
|
344
|
+
email=email,
|
345
|
+
attributes={
|
346
|
+
'scopes': scopes or list(STATIC_CONFIG['tokens']['scopes']),
|
347
|
+
},
|
348
|
+
instance=instance_connector,
|
349
|
+
)
|
337
350
|
info(f"Registering user '{user}' to Meerschaum instance '{instance_connector}'...")
|
338
|
-
result_tuple =
|
351
|
+
result_tuple = user.register(debug=debug)
|
339
352
|
print_tuple(result_tuple)
|
340
353
|
success[username] = result_tuple[0]
|
341
354
|
if success[username]:
|
@@ -443,6 +456,130 @@ def _complete_register_connectors(
|
|
443
456
|
return _complete_show_connectors(action)
|
444
457
|
|
445
458
|
|
459
|
+
def _register_tokens(
|
460
|
+
mrsm_instance: Optional[str] = None,
|
461
|
+
name: Optional[str] = None,
|
462
|
+
ttl_days: Optional[int] = None,
|
463
|
+
scopes: Optional[List[str]] = None,
|
464
|
+
end: Optional[datetime] = None,
|
465
|
+
force: bool = False,
|
466
|
+
yes: bool = False,
|
467
|
+
noask: bool = False,
|
468
|
+
nopretty: bool = False,
|
469
|
+
debug: bool = False,
|
470
|
+
**kwargs: Any
|
471
|
+
) -> mrsm.SuccessTuple:
|
472
|
+
"""
|
473
|
+
Register a new long-lived access token for API access.
|
474
|
+
Note that omitting and end time or TTL will generate token which does not expire.
|
475
|
+
|
476
|
+
Examples:
|
477
|
+
|
478
|
+
mrsm register token --end 2032-01-01
|
479
|
+
|
480
|
+
mrsm register token --ttl-days 1000
|
481
|
+
|
482
|
+
mrsm register token --name weather-sensor
|
483
|
+
|
484
|
+
"""
|
485
|
+
import json
|
486
|
+
from meerschaum.utils.schedule import parse_start_time
|
487
|
+
from meerschaum.core import User
|
488
|
+
from meerschaum.core.Token._Token import Token, _PLACEHOLDER_EXPIRATION
|
489
|
+
from meerschaum.connectors.parse import parse_instance_keys
|
490
|
+
from meerschaum.utils.prompt import yes_no, choose
|
491
|
+
from meerschaum.utils.formatting import make_header, print_tuple
|
492
|
+
from meerschaum.utils.dtypes import value_is_null
|
493
|
+
|
494
|
+
expiration = (
|
495
|
+
end
|
496
|
+
if end is not None
|
497
|
+
else (
|
498
|
+
parse_start_time(f"starting in {ttl_days} days")
|
499
|
+
if ttl_days
|
500
|
+
else _PLACEHOLDER_EXPIRATION
|
501
|
+
)
|
502
|
+
)
|
503
|
+
|
504
|
+
instance_connector = parse_instance_keys(mrsm_instance)
|
505
|
+
user = None
|
506
|
+
if instance_connector.type != 'api':
|
507
|
+
usernames = instance_connector.get_users(debug=debug)
|
508
|
+
if not usernames:
|
509
|
+
return False, f"No users are registered to '{instance_connector}'."
|
510
|
+
|
511
|
+
username = choose(
|
512
|
+
"To which user should this token be registered? Enter the number.",
|
513
|
+
usernames,
|
514
|
+
)
|
515
|
+
else:
|
516
|
+
username = getattr(instance_connector, 'username')
|
517
|
+
|
518
|
+
if not username:
|
519
|
+
return False, "Cannot register a token without a user."
|
520
|
+
|
521
|
+
user_id = instance_connector.get_user_id(
|
522
|
+
User(username, instance=mrsm_instance),
|
523
|
+
debug=debug,
|
524
|
+
)
|
525
|
+
if user_id is None:
|
526
|
+
return False, f"Cannot load ID for user '{username}'."
|
527
|
+
|
528
|
+
user = User(username, user_id=user_id, instance=mrsm_instance)
|
529
|
+
|
530
|
+
token = Token(
|
531
|
+
label=name,
|
532
|
+
expiration=expiration,
|
533
|
+
scopes=scopes,
|
534
|
+
user=user,
|
535
|
+
instance=mrsm_instance,
|
536
|
+
)
|
537
|
+
|
538
|
+
register_success, register_msg = token.register(debug=debug)
|
539
|
+
token_id = token.id
|
540
|
+
token_secret = token.secret
|
541
|
+
if not register_success:
|
542
|
+
return False, f"Failed to register token '{token.label}':\n{register_msg}"
|
543
|
+
|
544
|
+
token_model = token.to_model(refresh=True)
|
545
|
+
token_kwargs = dict(token_model)
|
546
|
+
token_kwargs['id'] = token_id
|
547
|
+
token_kwargs['secret'] = token_secret
|
548
|
+
token = Token(**token_kwargs)
|
549
|
+
|
550
|
+
if not nopretty:
|
551
|
+
print_tuple(
|
552
|
+
(
|
553
|
+
True,
|
554
|
+
(
|
555
|
+
f"Registered token '{token}'.\n "
|
556
|
+
"Write down the client secret, because it won't be shown again."
|
557
|
+
)
|
558
|
+
),
|
559
|
+
calm=True
|
560
|
+
)
|
561
|
+
|
562
|
+
msg_to_print = (
|
563
|
+
(
|
564
|
+
make_header(f"Attributes for token '{token}':") + "\n"
|
565
|
+
+ f" - Client ID: {token_model.id}\n"
|
566
|
+
+ f" - Client Secret: {token_secret}\n"
|
567
|
+
+ " - Expiration: "
|
568
|
+
+ (
|
569
|
+
token.expiration.isoformat()
|
570
|
+
if not value_is_null(token.expiration)
|
571
|
+
else 'Does not expire.'
|
572
|
+
)
|
573
|
+
+ "\n"
|
574
|
+
+ f" - API Key: {token.get_api_key()}\n"
|
575
|
+
)
|
576
|
+
if not nopretty
|
577
|
+
else json.dumps({'secret': token_secret, **dict(token_model)})
|
578
|
+
)
|
579
|
+
print(msg_to_print)
|
580
|
+
return True, f"Successfully registered token '{token.label}'."
|
581
|
+
|
582
|
+
|
446
583
|
### NOTE: This must be the final statement of the module.
|
447
584
|
### Any subactions added below these lines will not
|
448
585
|
### be added to the `help` docstring.
|
meerschaum/actions/reload.py
CHANGED
@@ -9,13 +9,30 @@ Reload the running Meerschaum instance.
|
|
9
9
|
from __future__ import annotations
|
10
10
|
from meerschaum.utils.typing import Any, SuccessTuple, List, Optional
|
11
11
|
|
12
|
+
|
12
13
|
def reload(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
action: Optional[List[str]] = None,
|
15
|
+
debug: bool = False,
|
16
|
+
_stop_daemons: bool = True,
|
17
|
+
**kw: Any
|
18
|
+
) -> SuccessTuple:
|
17
19
|
"""
|
18
20
|
Reload the running Meerschaum instance.
|
19
21
|
"""
|
20
22
|
from meerschaum.utils.packages import reload_meerschaum
|
21
|
-
|
23
|
+
from meerschaum.actions import actions
|
24
|
+
|
25
|
+
if _stop_daemons:
|
26
|
+
from meerschaum._internal.cli.workers import get_existing_cli_worker_indices
|
27
|
+
indices = get_existing_cli_worker_indices()
|
28
|
+
cli_action = 'restart' if indices else 'stop'
|
29
|
+
|
30
|
+
stop_daemon_success, stop_daemon_msg = actions[cli_action](['daemons'], debug=debug, **kw)
|
31
|
+
if not stop_daemon_success:
|
32
|
+
return stop_daemon_success, stop_daemon_msg
|
33
|
+
|
34
|
+
reload_success, reload_msg = reload_meerschaum(debug=debug)
|
35
|
+
if not reload_success:
|
36
|
+
return reload_success, reload_msg
|
37
|
+
|
38
|
+
return True, "Success"
|
meerschaum/actions/restart.py
CHANGED
@@ -7,6 +7,7 @@ Restart stopped jobs which have not been manually stopped.
|
|
7
7
|
|
8
8
|
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
|
9
9
|
|
10
|
+
|
10
11
|
def restart(
|
11
12
|
action: Optional[List[str]] = None,
|
12
13
|
executor_keys: Optional[str] = None,
|
@@ -18,6 +19,7 @@ def restart(
|
|
18
19
|
from meerschaum.actions import choose_subaction
|
19
20
|
attach_options = {
|
20
21
|
'jobs': _restart_jobs,
|
22
|
+
'daemons': _restart_daemons,
|
21
23
|
}
|
22
24
|
return choose_subaction(action, attach_options, executor_keys=executor_keys, **kwargs)
|
23
25
|
|
@@ -111,3 +113,15 @@ def _restart_jobs(
|
|
111
113
|
time.sleep(min_seconds)
|
112
114
|
|
113
115
|
return check_success, check_msg
|
116
|
+
|
117
|
+
|
118
|
+
def _restart_daemons(
|
119
|
+
action: Optional[List[str]] = None,
|
120
|
+
**kwargs
|
121
|
+
) -> SuccessTuple:
|
122
|
+
"""
|
123
|
+
Restart the CLI daemons.
|
124
|
+
"""
|
125
|
+
from meerschaum.actions import actions
|
126
|
+
kwargs['force'] = True
|
127
|
+
return actions['start'](['daemons'], **kwargs)
|
meerschaum/actions/show.py
CHANGED
@@ -45,6 +45,8 @@ def show(
|
|
45
45
|
'tags' : _show_tags,
|
46
46
|
'schedules' : _show_schedules,
|
47
47
|
'venvs' : _show_venvs,
|
48
|
+
'tokens' : _show_tokens,
|
49
|
+
'daemons' : _show_daemons,
|
48
50
|
}
|
49
51
|
return choose_subaction(action, show_options, **kw)
|
50
52
|
|
@@ -113,11 +115,11 @@ def _show_help(**kw: Any) -> SuccessTuple:
|
|
113
115
|
|
114
116
|
|
115
117
|
def _show_config(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
118
|
+
action: Optional[List[str]] = None,
|
119
|
+
debug: bool = False,
|
120
|
+
nopretty: bool = False,
|
121
|
+
**kw: Any
|
122
|
+
) -> SuccessTuple:
|
121
123
|
"""
|
122
124
|
Show the configuration dictionary.
|
123
125
|
Sub-actions defined in the action list are recursive indices in the config dictionary.
|
@@ -204,7 +206,7 @@ def _show_version(nopretty: bool = False, **kw : Any) -> SuccessTuple:
|
|
204
206
|
msg = "Meerschaum v" + version
|
205
207
|
_print = info
|
206
208
|
_print(msg)
|
207
|
-
return
|
209
|
+
return True, "Success"
|
208
210
|
|
209
211
|
|
210
212
|
def _show_connectors(
|
@@ -562,6 +564,7 @@ def _complete_show_packages(
|
|
562
564
|
|
563
565
|
return possibilities
|
564
566
|
|
567
|
+
|
565
568
|
def _show_jobs(
|
566
569
|
action: Optional[List[str]] = None,
|
567
570
|
executor_keys: Optional[str] = None,
|
@@ -762,7 +765,7 @@ def _show_environment(
|
|
762
765
|
"""
|
763
766
|
import os
|
764
767
|
from meerschaum.utils.formatting import pprint
|
765
|
-
from meerschaum.config.
|
768
|
+
from meerschaum.config.environment import get_env_vars
|
766
769
|
pprint(
|
767
770
|
{
|
768
771
|
env_var: os.environ[env_var]
|
@@ -789,34 +792,22 @@ def _show_tags(
|
|
789
792
|
from meerschaum.utils.formatting import pipe_repr, UNICODE, ANSI
|
790
793
|
from meerschaum.utils.pool import get_pool
|
791
794
|
from meerschaum.config import get_config
|
795
|
+
from meerschaum.connectors.parse import parse_instance_keys
|
792
796
|
rich_tree, rich_panel, rich_text, rich_console, rich_columns = (
|
793
797
|
mrsm.attempt_import('rich.tree', 'rich.panel', 'rich.text', 'rich.console', 'rich.columns')
|
794
798
|
)
|
795
|
-
panel = rich_panel.Panel.fit('Tags')
|
796
|
-
tree = rich_tree.Tree(panel)
|
797
799
|
action = action or []
|
798
800
|
tags = action + (tags or [])
|
799
|
-
pipes = mrsm.get_pipes(as_list=True, tags=tags, **kwargs)
|
800
|
-
if not pipes:
|
801
|
-
return False, f"No pipes were found with the given tags."
|
802
801
|
|
803
|
-
pool = get_pool(workers=workers)
|
804
802
|
tag_prefix = get_config('formatting', 'pipes', 'unicode', 'icons', 'tag') if UNICODE else ''
|
805
803
|
tag_style = get_config('formatting', 'pipes', 'ansi', 'styles', 'tags') if ANSI else None
|
806
804
|
|
807
|
-
tags_pipes =
|
808
|
-
|
809
|
-
|
810
|
-
pipes_tags = dict(pool.map(gather_pipe_tags, pipes))
|
811
|
-
|
812
|
-
for pipe, tags in pipes_tags.items():
|
813
|
-
for tag in tags:
|
814
|
-
if action and tag not in action:
|
815
|
-
continue
|
816
|
-
tags_pipes[tag].append(pipe)
|
805
|
+
tags_pipes = mrsm.get_pipes(as_tags_dict=True, tags=tags, **kwargs)
|
806
|
+
if action:
|
807
|
+
tags_pipes = {tag: pipes for tag, pipes in tags_pipes.items() if tag in action}
|
817
808
|
|
818
809
|
columns = []
|
819
|
-
sorted_tags = sorted(
|
810
|
+
sorted_tags = sorted(list(tags_pipes))
|
820
811
|
for tag in sorted_tags:
|
821
812
|
_pipes = tags_pipes[tag]
|
822
813
|
tag_text = (
|
@@ -904,9 +895,7 @@ def _show_schedules(
|
|
904
895
|
return True, "Success"
|
905
896
|
|
906
897
|
|
907
|
-
def _show_venvs(
|
908
|
-
**kwargs: Any
|
909
|
-
):
|
898
|
+
def _show_venvs(**kwargs: Any) -> SuccessTuple:
|
910
899
|
"""
|
911
900
|
Print the available virtual environments in the current MRSM_ROOT_DIR.
|
912
901
|
"""
|
@@ -921,12 +910,176 @@ def _show_venvs(
|
|
921
910
|
for _venv in os.listdir(VIRTENV_RESOURCES_PATH)
|
922
911
|
if venv_exists(_venv)
|
923
912
|
]
|
924
|
-
print_options(
|
925
|
-
|
926
|
-
|
927
|
-
|
913
|
+
print_options(venvs, name='Virtual Environments:', **kwargs)
|
914
|
+
return True, "Success"
|
915
|
+
|
916
|
+
|
917
|
+
def _show_tokens(
|
918
|
+
action: Optional[List[str]] = None,
|
919
|
+
mrsm_instance: Optional[str] = None,
|
920
|
+
nopretty: bool = False,
|
921
|
+
debug: bool = False,
|
922
|
+
**kwargs: Any
|
923
|
+
) -> SuccessTuple:
|
924
|
+
"""
|
925
|
+
Print a table of the registered tokens on the instance.
|
926
|
+
"""
|
927
|
+
import json
|
928
|
+
import uuid
|
929
|
+
from meerschaum.connectors.parse import parse_instance_keys
|
930
|
+
from meerschaum.utils.dtypes import value_is_null, json_serialize_value
|
931
|
+
from meerschaum.utils.misc import is_uuid
|
932
|
+
from meerschaum.utils.packages import import_rich
|
933
|
+
from meerschaum.utils.formatting import UNICODE, get_console
|
934
|
+
rich = import_rich()
|
935
|
+
rich_table, rich_json, rich_box = mrsm.attempt_import('rich.table', 'rich.json', 'rich.box')
|
936
|
+
|
937
|
+
conn = parse_instance_keys(mrsm_instance)
|
938
|
+
|
939
|
+
labels = [
|
940
|
+
label
|
941
|
+
for label in (action or [])
|
942
|
+
if not is_uuid(label)
|
943
|
+
]
|
944
|
+
potential_token_ids = [
|
945
|
+
uuid.UUID(potential_id)
|
946
|
+
for potential_id in (action or [])
|
947
|
+
if is_uuid(potential_id)
|
948
|
+
]
|
949
|
+
|
950
|
+
tokens = conn.get_tokens(
|
951
|
+
labels=(labels or None),
|
952
|
+
ids=(potential_token_ids or None),
|
953
|
+
debug=debug,
|
954
|
+
)
|
955
|
+
|
956
|
+
if nopretty:
|
957
|
+
for token in tokens:
|
958
|
+
print(json.dumps({
|
959
|
+
'id': str(token.id),
|
960
|
+
'label': token.label,
|
961
|
+
'scopes': token.scopes,
|
962
|
+
'expiration': (
|
963
|
+
token.expiration.isoformat()
|
964
|
+
if not value_is_null(token.expiration)
|
965
|
+
else None
|
966
|
+
),
|
967
|
+
'creation': (token.creation.isoformat() if not value_is_null(token.creation) else None),
|
968
|
+
'user': (token.user.username if token.user is not None else None),
|
969
|
+
'is_valid': token.is_valid,
|
970
|
+
}))
|
971
|
+
return True, "Success"
|
972
|
+
|
973
|
+
if len(tokens) == 1:
|
974
|
+
token = tokens[0]
|
975
|
+
tokens_json = json.dumps({
|
976
|
+
'id': str(token.id),
|
977
|
+
'label': token.label,
|
978
|
+
'scopes': token.scopes,
|
979
|
+
'creation': (token.creation.isoformat() if not value_is_null(token.creation) else None),
|
980
|
+
'expiration': (token.expiration.isoformat() if not value_is_null(token.expiration) else None),
|
981
|
+
'user': (token.user.username if token.user is not None else None),
|
982
|
+
'is_valid': token.is_valid,
|
983
|
+
}, default=json_serialize_value, indent=4)
|
984
|
+
get_console().print(rich_json.JSON(tokens_json))
|
985
|
+
|
986
|
+
return True, "Success"
|
987
|
+
|
988
|
+
is_valid_true = (
|
989
|
+
"🟢"
|
990
|
+
if UNICODE
|
991
|
+
else "[+]"
|
992
|
+
)
|
993
|
+
is_valid_false = (
|
994
|
+
"🔴"
|
995
|
+
if UNICODE
|
996
|
+
else "[-]"
|
997
|
+
)
|
998
|
+
|
999
|
+
table = rich_table.Table(
|
1000
|
+
title=f"Registered Tokens on instance '{conn}'",
|
1001
|
+
box=rich_box.ROUNDED,
|
1002
|
+
title_style='bold',
|
928
1003
|
)
|
1004
|
+
table.add_column("ID")
|
1005
|
+
table.add_column("Label")
|
1006
|
+
table.add_column("User")
|
1007
|
+
table.add_column("Expiration")
|
1008
|
+
table.add_column("Valid")
|
1009
|
+
|
1010
|
+
for token in tokens:
|
1011
|
+
table.add_row(
|
1012
|
+
str(token.id),
|
1013
|
+
token.label,
|
1014
|
+
(token.user.username if token.user is not None else ""),
|
1015
|
+
(
|
1016
|
+
token.expiration.isoformat()
|
1017
|
+
if not value_is_null(token.expiration)
|
1018
|
+
else 'Does not expire'
|
1019
|
+
),
|
1020
|
+
(is_valid_true if token.is_valid else is_valid_false),
|
1021
|
+
)
|
1022
|
+
|
1023
|
+
mrsm.pprint(table)
|
1024
|
+
return True, "Success"
|
1025
|
+
|
1026
|
+
|
1027
|
+
def _show_daemons() -> SuccessTuple:
|
1028
|
+
"""
|
1029
|
+
Print information about the running CLI daemons.
|
1030
|
+
"""
|
1031
|
+
from meerschaum._internal.cli.workers import get_existing_cli_workers
|
1032
|
+
workers = get_existing_cli_workers()
|
1033
|
+
if not workers:
|
1034
|
+
return True, "No CLI daemons are running."
|
1035
|
+
|
1036
|
+
rich_table, rich_box, rich_text = mrsm.attempt_import('rich.table', 'rich.box', 'rich.text')
|
1037
|
+
table = rich_table.Table(
|
1038
|
+
rich_table.Column("Index", justify='center'),
|
1039
|
+
rich_table.Column("Status"),
|
1040
|
+
rich_table.Column("Locked", justify='center'),
|
1041
|
+
rich_table.Column("Ready", justify='center'),
|
1042
|
+
rich_table.Column("Actions"),
|
1043
|
+
title='CLI Daemons',
|
1044
|
+
box=rich_box.ROUNDED,
|
1045
|
+
title_style='bold',
|
1046
|
+
)
|
1047
|
+
|
1048
|
+
running_icon = mrsm.get_config('formatting', 'emoji', 'running')
|
1049
|
+
paused_icon = mrsm.get_config('formatting', 'emoji', 'paused')
|
1050
|
+
stopped_icon = mrsm.get_config('formatting', 'emoji', 'stopped')
|
1051
|
+
locked_icon = mrsm.get_config('formatting', 'emoji', 'locked')
|
1052
|
+
unlocked_icon = mrsm.get_config('formatting', 'emoji', 'unlocked')
|
1053
|
+
status_styles = {
|
1054
|
+
'running': 'green',
|
1055
|
+
'stopped': 'red',
|
1056
|
+
'paused': 'yellow',
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
for worker in workers:
|
1060
|
+
status = worker.job.status
|
1061
|
+
status_text = rich_text.Text(
|
1062
|
+
status,
|
1063
|
+
style=status_styles[status],
|
1064
|
+
)
|
1065
|
+
if not worker.is_ready():
|
1066
|
+
ready_icon = stopped_icon
|
1067
|
+
else:
|
1068
|
+
ready_icon = (
|
1069
|
+
running_icon
|
1070
|
+
if status == 'running'
|
1071
|
+
else paused_icon
|
1072
|
+
)
|
1073
|
+
|
1074
|
+
table.add_row(
|
1075
|
+
str(worker.ix),
|
1076
|
+
status_text,
|
1077
|
+
(locked_icon if worker.lock_path.exists() else unlocked_icon),
|
1078
|
+
ready_icon,
|
1079
|
+
str(worker.job.daemon.rotating_log.get_latest_subfile_index()),
|
1080
|
+
)
|
929
1081
|
|
1082
|
+
mrsm.pprint(table)
|
930
1083
|
return True, "Success"
|
931
1084
|
|
932
1085
|
|