meerschaum 3.0.0rc3__py3-none-any.whl → 3.0.0rc7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerschaum/_internal/arguments/_parser.py +14 -2
- 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 +434 -0
- meerschaum/_internal/docs/index.py +1 -2
- meerschaum/_internal/entry.py +44 -8
- meerschaum/_internal/shell/Shell.py +113 -19
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +3 -1
- 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 +39 -11
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +27 -8
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +13 -7
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +69 -4
- meerschaum/actions/start.py +135 -14
- meerschaum/actions/stop.py +36 -3
- meerschaum/actions/sync.py +6 -1
- meerschaum/api/__init__.py +35 -13
- meerschaum/api/_events.py +7 -2
- meerschaum/api/_oauth2.py +47 -4
- meerschaum/api/dash/callbacks/dashboard.py +103 -97
- meerschaum/api/dash/callbacks/jobs.py +3 -2
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +136 -57
- meerschaum/api/dash/callbacks/register.py +9 -2
- meerschaum/api/dash/callbacks/tokens.py +2 -1
- meerschaum/api/dash/components.py +6 -7
- meerschaum/api/dash/keys.py +17 -1
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +14 -4
- meerschaum/api/dash/pipes.py +186 -65
- meerschaum/api/dash/tokens.py +1 -1
- meerschaum/api/dash/webterm.py +14 -6
- meerschaum/api/models/_pipes.py +7 -1
- 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 +1 -0
- meerschaum/api/routes/_jobs.py +23 -11
- meerschaum/api/routes/_login.py +73 -5
- meerschaum/api/routes/_pipes.py +6 -4
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +60 -13
- meerschaum/config/_default.py +89 -61
- meerschaum/config/_edit.py +10 -8
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +4 -2
- meerschaum/config/_paths.py +127 -12
- meerschaum/config/_read_config.py +20 -10
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +7 -5
- meerschaum/connectors/_Connector.py +1 -2
- meerschaum/connectors/__init__.py +37 -2
- meerschaum/connectors/api/_APIConnector.py +1 -1
- meerschaum/connectors/api/_jobs.py +11 -0
- meerschaum/connectors/api/_pipes.py +7 -1
- meerschaum/connectors/instance/_plugins.py +9 -1
- meerschaum/connectors/instance/_tokens.py +20 -3
- meerschaum/connectors/instance/_users.py +8 -1
- meerschaum/connectors/parse.py +1 -1
- meerschaum/connectors/sql/_create_engine.py +3 -0
- meerschaum/connectors/sql/_pipes.py +98 -79
- meerschaum/connectors/sql/_users.py +8 -1
- meerschaum/connectors/sql/tables/__init__.py +20 -3
- meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
- meerschaum/connectors/valkey/_pipes.py +7 -5
- meerschaum/core/Pipe/__init__.py +62 -72
- meerschaum/core/Pipe/_attributes.py +66 -90
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +0 -50
- 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 +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_sync.py +12 -18
- meerschaum/core/Plugin/_Plugin.py +7 -1
- meerschaum/core/Token/_Token.py +1 -1
- meerschaum/core/User/_User.py +1 -2
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +135 -35
- meerschaum/jobs/systemd.py +7 -2
- meerschaum/plugins/__init__.py +277 -81
- meerschaum/utils/_get_pipes.py +30 -4
- meerschaum/utils/daemon/Daemon.py +195 -41
- 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 +18 -5
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/debug.py +34 -4
- meerschaum/utils/dtypes/__init__.py +5 -1
- meerschaum/utils/formatting/__init__.py +4 -1
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +47 -46
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +16 -6
- meerschaum/utils/misc.py +18 -38
- meerschaum/utils/packages/__init__.py +15 -13
- meerschaum/utils/packages/_packages.py +1 -0
- meerschaum/utils/pipes.py +39 -7
- meerschaum/utils/process.py +1 -1
- meerschaum/utils/prompt.py +171 -144
- meerschaum/utils/sql.py +12 -2
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/venv/__init__.py +2 -0
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/METADATA +3 -1
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/RECORD +125 -119
- meerschaum/config/_environment.py +0 -145
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/NOTICE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/zip-safe +0 -0
meerschaum/actions/delete.py
CHANGED
@@ -18,7 +18,7 @@ def delete(
|
|
18
18
|
Delete an element.
|
19
19
|
|
20
20
|
Command:
|
21
|
-
`delete {config, pipes, plugins, users, connectors, jobs}`
|
21
|
+
`delete {config, pipes, plugins, users, connectors, jobs, venvs}`
|
22
22
|
|
23
23
|
"""
|
24
24
|
from meerschaum.actions import choose_subaction
|
@@ -159,7 +159,9 @@ def _delete_config(
|
|
159
159
|
answer = yes_no(
|
160
160
|
"Are you sure you want to delete the following configuration files?" +
|
161
161
|
f"{sep + sep.join([str(p) for p in paths])}\n",
|
162
|
-
default='n',
|
162
|
+
default='n',
|
163
|
+
noask=noask,
|
164
|
+
yes=yes,
|
163
165
|
)
|
164
166
|
|
165
167
|
if answer or force:
|
meerschaum/actions/edit.py
CHANGED
@@ -67,7 +67,12 @@ def _complete_edit(
|
|
67
67
|
return default_action_completer(action=(['edit'] + action), **kw)
|
68
68
|
|
69
69
|
|
70
|
-
def _edit_config(
|
70
|
+
def _edit_config(
|
71
|
+
action: Optional[List[str]] = None,
|
72
|
+
noask: bool = False,
|
73
|
+
debug: bool = False,
|
74
|
+
**kwargs: Any
|
75
|
+
) -> SuccessTuple:
|
71
76
|
"""
|
72
77
|
Edit Meerschaum configuration files.
|
73
78
|
|
@@ -87,11 +92,26 @@ def _edit_config(action: Optional[List[str]] = None, **kw: Any) -> SuccessTuple:
|
|
87
92
|
```
|
88
93
|
"""
|
89
94
|
from meerschaum.config._edit import edit_config
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
+
from meerschaum.config._read_config import get_possible_keys
|
96
|
+
from meerschaum.actions import actions
|
97
|
+
from meerschaum.utils.prompt import choose
|
98
|
+
|
99
|
+
if not action:
|
100
|
+
action = [
|
101
|
+
choose(
|
102
|
+
"Choose a configuration file to edit:",
|
103
|
+
get_possible_keys(),
|
104
|
+
default='meerschaum',
|
105
|
+
noask=noask,
|
106
|
+
)
|
107
|
+
]
|
108
|
+
|
109
|
+
edit_success, edit_msg = edit_config(keys=action, debug=debug, **kwargs)
|
110
|
+
if not edit_success:
|
111
|
+
return edit_success, edit_msg
|
112
|
+
|
113
|
+
return actions['reload'](debug=debug)
|
114
|
+
|
95
115
|
|
96
116
|
def _complete_edit_config(action: Optional[List[str]] = None, **kw: Any) -> List[str]:
|
97
117
|
from meerschaum.config._read_config import get_possible_keys
|
@@ -343,7 +363,6 @@ def _edit_plugins(
|
|
343
363
|
from meerschaum.utils.warnings import warn
|
344
364
|
from meerschaum.utils.prompt import prompt, yes_no
|
345
365
|
from meerschaum.utils.misc import edit_file
|
346
|
-
from meerschaum.utils.packages import reload_meerschaum
|
347
366
|
from meerschaum.actions import actions
|
348
367
|
|
349
368
|
if not action:
|
@@ -376,7 +395,7 @@ def _edit_plugins(
|
|
376
395
|
continue
|
377
396
|
|
378
397
|
edit_file(plugin_file_path)
|
379
|
-
|
398
|
+
actions['reload'](debug=debug)
|
380
399
|
|
381
400
|
return True, "Success"
|
382
401
|
|
meerschaum/actions/login.py
CHANGED
@@ -10,13 +10,13 @@ from __future__ import annotations
|
|
10
10
|
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
|
11
11
|
|
12
12
|
def login(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
action: Optional[List[str]] = None,
|
14
|
+
connector_keys: Optional[List[str]] = None,
|
15
|
+
yes: bool = False,
|
16
|
+
noask: bool = False,
|
17
|
+
debug: bool = False,
|
18
|
+
**kw: Any
|
19
|
+
) -> SuccessTuple:
|
20
20
|
"""
|
21
21
|
Log into a Meerschaum API instance.
|
22
22
|
"""
|
@@ -56,7 +56,7 @@ def login(
|
|
56
56
|
for k in _keys:
|
57
57
|
try:
|
58
58
|
_connectors.append(parse_instance_keys(k))
|
59
|
-
except Exception
|
59
|
+
except Exception:
|
60
60
|
warn(f"Unable to build connector '{k}'. Is it registered?", stack=False)
|
61
61
|
|
62
62
|
meerschaum_config = get_config('meerschaum')
|
meerschaum/actions/register.py
CHANGED
@@ -512,14 +512,20 @@ def _register_tokens(
|
|
512
512
|
"To which user should this token be registered? Enter the number.",
|
513
513
|
usernames,
|
514
514
|
)
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
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}'."
|
521
527
|
|
522
|
-
|
528
|
+
user = User(username, user_id=user_id, instance=mrsm_instance)
|
523
529
|
|
524
530
|
token = Token(
|
525
531
|
label=name,
|
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
@@ -46,6 +46,7 @@ def show(
|
|
46
46
|
'schedules' : _show_schedules,
|
47
47
|
'venvs' : _show_venvs,
|
48
48
|
'tokens' : _show_tokens,
|
49
|
+
'daemons' : _show_daemons,
|
49
50
|
}
|
50
51
|
return choose_subaction(action, show_options, **kw)
|
51
52
|
|
@@ -205,7 +206,7 @@ def _show_version(nopretty: bool = False, **kw : Any) -> SuccessTuple:
|
|
205
206
|
msg = "Meerschaum v" + version
|
206
207
|
_print = info
|
207
208
|
_print(msg)
|
208
|
-
return
|
209
|
+
return True, "Success"
|
209
210
|
|
210
211
|
|
211
212
|
def _show_connectors(
|
@@ -563,6 +564,7 @@ def _complete_show_packages(
|
|
563
564
|
|
564
565
|
return possibilities
|
565
566
|
|
567
|
+
|
566
568
|
def _show_jobs(
|
567
569
|
action: Optional[List[str]] = None,
|
568
570
|
executor_keys: Optional[str] = None,
|
@@ -763,7 +765,7 @@ def _show_environment(
|
|
763
765
|
"""
|
764
766
|
import os
|
765
767
|
from meerschaum.utils.formatting import pprint
|
766
|
-
from meerschaum.config.
|
768
|
+
from meerschaum.config.environment import get_env_vars
|
767
769
|
pprint(
|
768
770
|
{
|
769
771
|
env_var: os.environ[env_var]
|
@@ -930,7 +932,7 @@ def _show_tokens(
|
|
930
932
|
from meerschaum.utils.packages import import_rich
|
931
933
|
from meerschaum.utils.formatting import UNICODE, get_console
|
932
934
|
rich = import_rich()
|
933
|
-
rich_table, rich_json = mrsm.attempt_import('rich.table', 'rich.json')
|
935
|
+
rich_table, rich_json, rich_box = mrsm.attempt_import('rich.table', 'rich.json', 'rich.box')
|
934
936
|
|
935
937
|
conn = parse_instance_keys(mrsm_instance)
|
936
938
|
|
@@ -994,7 +996,11 @@ def _show_tokens(
|
|
994
996
|
else "[-]"
|
995
997
|
)
|
996
998
|
|
997
|
-
table = rich_table.Table(
|
999
|
+
table = rich_table.Table(
|
1000
|
+
title=f"Registered Tokens on instance '{conn}'",
|
1001
|
+
box=rich_box.ROUNDED,
|
1002
|
+
title_style='bold',
|
1003
|
+
)
|
998
1004
|
table.add_column("ID")
|
999
1005
|
table.add_column("Label")
|
1000
1006
|
table.add_column("User")
|
@@ -1018,6 +1024,65 @@ def _show_tokens(
|
|
1018
1024
|
return True, "Success"
|
1019
1025
|
|
1020
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
|
+
)
|
1081
|
+
|
1082
|
+
mrsm.pprint(table)
|
1083
|
+
return True, "Success"
|
1084
|
+
|
1085
|
+
|
1021
1086
|
### NOTE: This must be the final statement of the module.
|
1022
1087
|
### Any subactions added below these lines will not
|
1023
1088
|
### be added to the `help` docstring.
|
meerschaum/actions/start.py
CHANGED
@@ -7,6 +7,8 @@ Start subsystems (API server, logging daemon, etc.).
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
+
|
11
|
+
import meerschaum as mrsm
|
10
12
|
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any, Union, Dict
|
11
13
|
|
12
14
|
|
@@ -25,6 +27,7 @@ def start(
|
|
25
27
|
'webterm': _start_webterm,
|
26
28
|
'connectors': _start_connectors,
|
27
29
|
'pipeline': _start_pipeline,
|
30
|
+
'daemons': _start_daemons,
|
28
31
|
}
|
29
32
|
return choose_subaction(action, options, **kw)
|
30
33
|
|
@@ -308,6 +311,7 @@ def _start_gui(
|
|
308
311
|
action: Optional[List[str]] = None,
|
309
312
|
mrsm_instance: Optional[str] = None,
|
310
313
|
port: Optional[int] = None,
|
314
|
+
webterm_port: Optional[int] = None,
|
311
315
|
debug: bool = False,
|
312
316
|
**kw
|
313
317
|
) -> SuccessTuple:
|
@@ -321,7 +325,6 @@ def _start_gui(
|
|
321
325
|
|
322
326
|
from meerschaum.utils.venv import venv_exec
|
323
327
|
from meerschaum.utils.packages import attempt_import
|
324
|
-
from meerschaum.utils.warnings import warn
|
325
328
|
from meerschaum.utils.debug import dprint
|
326
329
|
from meerschaum.utils.networking import find_open_ports
|
327
330
|
from meerschaum.connectors.parse import parse_instance_keys
|
@@ -329,9 +332,10 @@ def _start_gui(
|
|
329
332
|
webview, requests = attempt_import('webview', 'requests')
|
330
333
|
|
331
334
|
success, msg = True, "Success"
|
332
|
-
host =
|
333
|
-
|
334
|
-
|
335
|
+
host = mrsm.get_config('webterm', 'host')
|
336
|
+
port = port or webterm_port
|
337
|
+
if not port:
|
338
|
+
port = mrsm.get_config('webterm', 'port')
|
335
339
|
|
336
340
|
if not is_webterm_running(host, port, session_id='mrsm'):
|
337
341
|
port = next(find_open_ports(port, 9000))
|
@@ -369,7 +373,7 @@ def _start_gui(
|
|
369
373
|
break
|
370
374
|
except Exception as e:
|
371
375
|
if debug:
|
372
|
-
dprint(e)
|
376
|
+
dprint(str(e))
|
373
377
|
continue
|
374
378
|
if starting_up is False:
|
375
379
|
return False, f"The webterm failed to start within {timeout} seconds."
|
@@ -417,7 +421,6 @@ def _start_webterm(
|
|
417
421
|
- `-i`, '--instance'
|
418
422
|
The default instance to use for the Webterm shell.
|
419
423
|
"""
|
420
|
-
import uuid
|
421
424
|
from meerschaum._internal.term import get_webterm_app_and_manager, tornado_ioloop
|
422
425
|
from meerschaum._internal.term.tools import (
|
423
426
|
is_webterm_running,
|
@@ -426,15 +429,17 @@ def _start_webterm(
|
|
426
429
|
)
|
427
430
|
from meerschaum.utils.networking import find_open_ports
|
428
431
|
from meerschaum.utils.warnings import info
|
432
|
+
from meerschaum.config.paths import WEBTERM_INTERNAL_RESOURCES_PATH
|
429
433
|
|
430
434
|
if host is None:
|
431
|
-
host =
|
435
|
+
host = mrsm.get_config('api', 'webterm', 'host')
|
432
436
|
if port is None:
|
433
|
-
port =
|
437
|
+
port = mrsm.get_config('api', 'webterm', 'port')
|
434
438
|
if sysargs is None:
|
435
439
|
sysargs = ['start', 'webterm']
|
436
440
|
session_id = 'mrsm'
|
437
|
-
|
441
|
+
|
442
|
+
env_path = WEBTERM_INTERNAL_RESOURCES_PATH / (str(port) + '.json')
|
438
443
|
|
439
444
|
if is_webterm_running(host, port, session_id=session_id):
|
440
445
|
if force:
|
@@ -445,11 +450,18 @@ def _start_webterm(
|
|
445
450
|
+ " Include `-f` to start another server on a new port\n"
|
446
451
|
+ " or specify a different port with `-p`."
|
447
452
|
)
|
453
|
+
|
454
|
+
tornado_app, term_manager = get_webterm_app_and_manager(
|
455
|
+
instance_keys=mrsm_instance,
|
456
|
+
port=port,
|
457
|
+
env_path=env_path,
|
458
|
+
)
|
448
459
|
if not nopretty:
|
449
460
|
info(
|
450
461
|
f"Starting the webterm at http://{host}:{port}/webterm/{session_id} ..."
|
451
462
|
"\n Press CTRL+C to quit."
|
452
463
|
)
|
464
|
+
|
453
465
|
tornado_app.listen(port, host)
|
454
466
|
loop = tornado_ioloop.IOLoop.instance()
|
455
467
|
try:
|
@@ -462,10 +474,15 @@ def _start_webterm(
|
|
462
474
|
term_manager.shutdown()
|
463
475
|
loop.close()
|
464
476
|
|
465
|
-
sessions = get_mrsm_tmux_sessions()
|
477
|
+
sessions = get_mrsm_tmux_sessions(port=port)
|
466
478
|
for session in sessions:
|
467
479
|
kill_tmux_session(session)
|
468
480
|
|
481
|
+
try:
|
482
|
+
env_path.unlink()
|
483
|
+
except Exception:
|
484
|
+
pass
|
485
|
+
|
469
486
|
return True, "Success"
|
470
487
|
|
471
488
|
|
@@ -483,7 +500,6 @@ def _start_connectors(
|
|
483
500
|
from meerschaum.connectors.parse import parse_instance_keys
|
484
501
|
from meerschaum.utils.pool import get_pool
|
485
502
|
from meerschaum.utils.warnings import warn
|
486
|
-
from meerschaum.utils.formatting import pprint
|
487
503
|
from meerschaum.utils.misc import items_str
|
488
504
|
if action is None:
|
489
505
|
action = []
|
@@ -575,7 +591,6 @@ def _start_pipeline(
|
|
575
591
|
"""
|
576
592
|
import json
|
577
593
|
import time
|
578
|
-
import sys
|
579
594
|
from meerschaum._internal.entry import entry
|
580
595
|
from meerschaum.utils.warnings import info, warn
|
581
596
|
from meerschaum.utils.misc import is_int
|
@@ -630,7 +645,7 @@ def _start_pipeline(
|
|
630
645
|
def do_entry() -> None:
|
631
646
|
nonlocal success, msg, proc
|
632
647
|
if timeout_seconds is None:
|
633
|
-
success, msg = entry(sub_args_line, _patch_args=patch_args)
|
648
|
+
success, msg = entry(sub_args_line, _patch_args=patch_args, _use_cli_daemon=False)
|
634
649
|
return
|
635
650
|
|
636
651
|
sub_args_line_escaped = sub_args_line.replace("'", "<QUOTE>")
|
@@ -640,7 +655,7 @@ def _start_pipeline(
|
|
640
655
|
"from meerschaum._internal.entry import entry\n\n"
|
641
656
|
f"sub_args_line = '{sub_args_line_escaped}'.replace(\"<QUOTE>\", \"'\")\n"
|
642
657
|
f"patch_args = json.loads('{patch_args_escaped_str}'.replace('<QUOTE>', \"'\"))\n"
|
643
|
-
"success, msg = entry(sub_args_line, _patch_args=patch_args)\n"
|
658
|
+
"success, msg = entry(sub_args_line, _patch_args=patch_args, _use_cli_daemon=False)\n"
|
644
659
|
f"print('{fence_begin}' + json.dumps((success, msg)) + '{fence_end}')"
|
645
660
|
)
|
646
661
|
proc = venv_exec(src, venv=None, as_proc=True)
|
@@ -688,6 +703,112 @@ def _start_pipeline(
|
|
688
703
|
return success, msg
|
689
704
|
|
690
705
|
|
706
|
+
def _start_daemons(
|
707
|
+
timeout_seconds: Union[int, float, None] = None,
|
708
|
+
yes: bool = False,
|
709
|
+
force: bool = False,
|
710
|
+
noask: bool = False,
|
711
|
+
debug: bool = False,
|
712
|
+
**kwargs
|
713
|
+
) -> SuccessTuple:
|
714
|
+
"""
|
715
|
+
Start the Meerschaum CLI daemon processes.
|
716
|
+
"""
|
717
|
+
from meerschaum.utils.warnings import warn, dprint
|
718
|
+
from meerschaum._internal.cli.daemons import (
|
719
|
+
get_cli_daemon,
|
720
|
+
get_cli_lock_path,
|
721
|
+
)
|
722
|
+
from meerschaum._internal.cli.workers import (
|
723
|
+
get_existing_cli_workers,
|
724
|
+
get_existing_cli_worker_indices,
|
725
|
+
)
|
726
|
+
from meerschaum.utils.prompt import yes_no
|
727
|
+
from meerschaum.actions import actions
|
728
|
+
|
729
|
+
workers = get_existing_cli_workers()
|
730
|
+
if not workers:
|
731
|
+
if debug:
|
732
|
+
dprint("No daemons are running, spawning a new process...")
|
733
|
+
workers = [get_cli_daemon()]
|
734
|
+
|
735
|
+
accepted_restart = False
|
736
|
+
any_daemons_are_running = any((worker.job.status == 'running') for worker in workers)
|
737
|
+
lock_paths = [get_cli_lock_path(ix) for ix in get_existing_cli_worker_indices()]
|
738
|
+
any_locks_exist = any(lock_path.exists() for lock_path in lock_paths)
|
739
|
+
|
740
|
+
if any_locks_exist:
|
741
|
+
warn(
|
742
|
+
"Locks are currently held by the CLI daemons.\n"
|
743
|
+
"Run again with `--force` to remove the locks.",
|
744
|
+
stack=False,
|
745
|
+
)
|
746
|
+
|
747
|
+
if not force:
|
748
|
+
return False, "Actions are currently running."
|
749
|
+
|
750
|
+
for lock_path in lock_paths:
|
751
|
+
try:
|
752
|
+
if lock_path.exists():
|
753
|
+
lock_path.unlink()
|
754
|
+
except Exception as e:
|
755
|
+
warn(f"Failed to release lock:\n{e}")
|
756
|
+
|
757
|
+
if any_daemons_are_running:
|
758
|
+
accepted_restart = force or yes_no(
|
759
|
+
"Restart running CLI daemons?",
|
760
|
+
yes=yes,
|
761
|
+
noask=noask,
|
762
|
+
default='n',
|
763
|
+
)
|
764
|
+
|
765
|
+
if not accepted_restart:
|
766
|
+
return True, "Daemons are already running; nothing to do."
|
767
|
+
|
768
|
+
stop_success, stop_msg = actions['stop'](
|
769
|
+
['daemons'],
|
770
|
+
timeout_seconds=timeout_seconds,
|
771
|
+
debug=debug,
|
772
|
+
)
|
773
|
+
if not stop_success:
|
774
|
+
return stop_success, stop_msg
|
775
|
+
|
776
|
+
worker = get_cli_daemon()
|
777
|
+
|
778
|
+
if debug:
|
779
|
+
dprint("Cleaning up CLI daemon...")
|
780
|
+
cleanup_success, cleanup_msg = worker.cleanup()
|
781
|
+
if not cleanup_success:
|
782
|
+
return cleanup_success, cleanup_msg
|
783
|
+
|
784
|
+
if debug:
|
785
|
+
dprint("Starting CLI daemon...")
|
786
|
+
|
787
|
+
start_success, start_msg = worker.job.start()
|
788
|
+
if not start_success:
|
789
|
+
return start_success, start_msg
|
790
|
+
|
791
|
+
return True, "Success"
|
792
|
+
|
793
|
+
|
794
|
+
def _start_worker(action: Optional[List[str]] = None, **kwargs: Any) -> SuccessTuple:
|
795
|
+
"""
|
796
|
+
Start a CLI worker process. This is intended for internal use only.
|
797
|
+
"""
|
798
|
+
from meerschaum._internal.cli.workers import ActionWorker
|
799
|
+
from meerschaum.utils.misc import is_int
|
800
|
+
|
801
|
+
if not action:
|
802
|
+
return False, "No worker index is provided."
|
803
|
+
|
804
|
+
if not is_int(action[0]):
|
805
|
+
return False, "Invalid worker index."
|
806
|
+
|
807
|
+
ix = int(action[0])
|
808
|
+
worker = ActionWorker(ix)
|
809
|
+
return worker.run()
|
810
|
+
|
811
|
+
|
691
812
|
### NOTE: This must be the final statement of the module.
|
692
813
|
### Any subactions added below these lines will not
|
693
814
|
### be added to the `help` docstring.
|
meerschaum/actions/stop.py
CHANGED
@@ -7,7 +7,7 @@ Stop running jobs that were started with `-d` or `start job`.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
from meerschaum.utils.typing import Optional, List, SuccessTuple, Any
|
10
|
+
from meerschaum.utils.typing import Optional, List, SuccessTuple, Any, Union
|
11
11
|
|
12
12
|
|
13
13
|
def stop(action: Optional[List[str]] = None, **kw) -> SuccessTuple:
|
@@ -17,6 +17,7 @@ def stop(action: Optional[List[str]] = None, **kw) -> SuccessTuple:
|
|
17
17
|
from meerschaum.actions import choose_subaction
|
18
18
|
options = {
|
19
19
|
'jobs': _stop_jobs,
|
20
|
+
'daemons': _stop_daemons,
|
20
21
|
}
|
21
22
|
return choose_subaction(action, options, **kw)
|
22
23
|
|
@@ -53,7 +54,7 @@ def _complete_stop(
|
|
53
54
|
return options[sub](action=action, **kw)
|
54
55
|
|
55
56
|
from meerschaum._internal.shell import default_action_completer
|
56
|
-
return default_action_completer(action=(['
|
57
|
+
return default_action_completer(action=(['stop'] + action), **kw)
|
57
58
|
|
58
59
|
|
59
60
|
def _stop_jobs(
|
@@ -113,7 +114,7 @@ def _stop_jobs(
|
|
113
114
|
|
114
115
|
if not jobs_to_stop:
|
115
116
|
if jobs:
|
116
|
-
return True, "The selected jobs are currently
|
117
|
+
return True, "The selected jobs are currently stopped."
|
117
118
|
return False, "No running, paused or restarting jobs to stop."
|
118
119
|
|
119
120
|
if not action:
|
@@ -163,6 +164,38 @@ def _stop_jobs(
|
|
163
164
|
return success, msg
|
164
165
|
|
165
166
|
|
167
|
+
def _stop_daemons(
|
168
|
+
timeout_seconds: Union[int, float, None] = None,
|
169
|
+
debug: bool = False,
|
170
|
+
**kwargs
|
171
|
+
) -> SuccessTuple:
|
172
|
+
"""
|
173
|
+
Stop the Meerschaum CLI daemon.
|
174
|
+
"""
|
175
|
+
import shutil
|
176
|
+
from meerschaum._internal.cli.workers import get_existing_cli_workers
|
177
|
+
from meerschaum.config.paths import CLI_RESOURCES_PATH
|
178
|
+
workers = get_existing_cli_workers()
|
179
|
+
|
180
|
+
for worker in workers:
|
181
|
+
stop_success, stop_msg = worker.job.stop(timeout_seconds=timeout_seconds, debug=debug)
|
182
|
+
if not stop_success:
|
183
|
+
return stop_success, stop_msg
|
184
|
+
|
185
|
+
cleanup_success, cleanup_msg = worker.cleanup(debug=debug)
|
186
|
+
if not cleanup_success:
|
187
|
+
return cleanup_success, cleanup_msg
|
188
|
+
|
189
|
+
try:
|
190
|
+
if CLI_RESOURCES_PATH.exists():
|
191
|
+
shutil.rmtree(CLI_RESOURCES_PATH)
|
192
|
+
CLI_RESOURCES_PATH.mkdir(parents=True, exist_ok=True)
|
193
|
+
except Exception as e:
|
194
|
+
return False, f"Failed to clean up CLI resources directory.\n{e}"
|
195
|
+
|
196
|
+
return True, "Success"
|
197
|
+
|
198
|
+
|
166
199
|
### NOTE: This must be the final statement of the module.
|
167
200
|
### Any subactions added below these lines will not
|
168
201
|
### be added to the `help` docstring.
|
meerschaum/actions/sync.py
CHANGED
@@ -289,6 +289,7 @@ def _sync_pipes(
|
|
289
289
|
from meerschaum.utils.formatting import print_pipes_results
|
290
290
|
from meerschaum._internal.static import STATIC_CONFIG
|
291
291
|
from meerschaum.utils.misc import interval_str
|
292
|
+
from meerschaum.utils.daemon import running_in_daemon
|
292
293
|
|
293
294
|
noninteractive_val = os.environ.get(STATIC_CONFIG['environment']['noninteractive'], None)
|
294
295
|
noninteractive = str(noninteractive_val).lower() in ('1', 'true', 'yes')
|
@@ -301,7 +302,11 @@ def _sync_pipes(
|
|
301
302
|
cooldown = 2 * (min_seconds + 1)
|
302
303
|
success_pipes, failure_pipes = [], []
|
303
304
|
while run:
|
304
|
-
_progress =
|
305
|
+
_progress = (
|
306
|
+
progress()
|
307
|
+
if (shell and not noninteractive and not running_in_daemon())
|
308
|
+
else None
|
309
|
+
)
|
305
310
|
cm = _progress if _progress is not None else contextlib.nullcontext()
|
306
311
|
|
307
312
|
lap_begin = time.perf_counter()
|