meerschaum 3.0.0rc4__py3-none-any.whl → 3.0.0rc8__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 +435 -0
- meerschaum/_internal/docs/index.py +1 -2
- meerschaum/_internal/entry.py +44 -8
- meerschaum/_internal/shell/Shell.py +115 -24
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +4 -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 +2 -2
- meerschaum/api/_oauth2.py +47 -4
- meerschaum/api/dash/callbacks/dashboard.py +29 -0
- meerschaum/api/dash/callbacks/jobs.py +3 -2
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/register.py +9 -2
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pipes.py +72 -36
- 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 +32 -12
- 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 +93 -79
- meerschaum/connectors/sql/_users.py +8 -1
- meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
- meerschaum/connectors/valkey/_pipes.py +7 -5
- meerschaum/core/Pipe/__init__.py +45 -71
- 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 +146 -36
- meerschaum/jobs/systemd.py +7 -2
- meerschaum/plugins/__init__.py +277 -81
- meerschaum/utils/daemon/Daemon.py +197 -42
- 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/_shell.py +33 -9
- meerschaum/utils/misc.py +22 -38
- meerschaum/utils/packages/__init__.py +15 -13
- meerschaum/utils/packages/_packages.py +1 -0
- meerschaum/utils/pipes.py +33 -5
- meerschaum/utils/process.py +1 -1
- meerschaum/utils/prompt.py +172 -143
- 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.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/METADATA +3 -1
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/RECORD +116 -110
- meerschaum/config/_environment.py +0 -145
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/licenses/NOTICE +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/zip-safe +0 -0
meerschaum/actions/api.py
CHANGED
@@ -6,7 +6,10 @@ Start the Meerschaum WebAPI with the `api` action.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from __future__ import annotations
|
9
|
+
|
9
10
|
import os
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
10
13
|
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
|
11
14
|
|
12
15
|
|
@@ -93,6 +96,7 @@ def _api_start(
|
|
93
96
|
action: Optional[List[str]] = None,
|
94
97
|
host: Optional[str] = None,
|
95
98
|
port: Optional[int] = None,
|
99
|
+
webterm_port: Optional[int] = None,
|
96
100
|
workers: Optional[int] = None,
|
97
101
|
mrsm_instance: Optional[str] = None,
|
98
102
|
no_dash: bool = False,
|
@@ -119,6 +123,10 @@ def _api_start(
|
|
119
123
|
The address to bind to.
|
120
124
|
If `None`, use '0.0.0.0'.
|
121
125
|
|
126
|
+
webterm_port: Optional[int], default None
|
127
|
+
Port to bind the webterm server to.
|
128
|
+
If `None`, use 8765.
|
129
|
+
|
122
130
|
workers: Optional[int], default None
|
123
131
|
How many worker threads to run.
|
124
132
|
If `None`, defaults to the number of CPU cores or 1 on Android.
|
@@ -149,8 +157,6 @@ def _api_start(
|
|
149
157
|
|
150
158
|
from meerschaum.utils.packages import (
|
151
159
|
attempt_import,
|
152
|
-
venv_contains_package,
|
153
|
-
pip_install,
|
154
160
|
run_python_package,
|
155
161
|
)
|
156
162
|
from meerschaum.utils.misc import is_int, filter_keywords
|
@@ -164,9 +170,10 @@ def _api_start(
|
|
164
170
|
API_UVICORN_CONFIG_PATH,
|
165
171
|
CACHE_RESOURCES_PATH,
|
166
172
|
PACKAGE_ROOT_PATH,
|
173
|
+
ROOT_DIR_PATH,
|
167
174
|
)
|
168
175
|
from meerschaum.config._patch import apply_patch_to_config
|
169
|
-
from meerschaum.config.
|
176
|
+
from meerschaum.config.environment import get_env_vars
|
170
177
|
from meerschaum._internal.static import STATIC_CONFIG, SERVER_ID
|
171
178
|
from meerschaum.connectors.parse import parse_instance_keys
|
172
179
|
from meerschaum.utils.pool import get_pool
|
@@ -187,9 +194,9 @@ def _api_start(
|
|
187
194
|
uvicorn_config_path = API_UVICORN_RESOURCES_PATH / SERVER_ID / 'config.json'
|
188
195
|
uvicorn_env_path = API_UVICORN_RESOURCES_PATH / SERVER_ID / 'uvicorn.env'
|
189
196
|
|
190
|
-
api_config = deepcopy(get_config('
|
197
|
+
api_config = deepcopy(get_config('api'))
|
191
198
|
cf = _config()
|
192
|
-
forwarded_allow_ips = get_config('
|
199
|
+
forwarded_allow_ips = get_config('api', 'uvicorn', 'forwarded_allow_ips')
|
193
200
|
uvicorn_config = api_config['uvicorn']
|
194
201
|
if port is None:
|
195
202
|
### default
|
@@ -223,7 +230,7 @@ def _api_start(
|
|
223
230
|
instance_connector = parse_instance_keys(mrsm_instance, debug=debug)
|
224
231
|
if instance_connector.type == 'api' and instance_connector.protocol != 'https':
|
225
232
|
allow_http_parent = get_config(
|
226
|
-
'
|
233
|
+
'api', 'permissions', 'chaining', 'insecure_parent_instance'
|
227
234
|
)
|
228
235
|
if not allow_http_parent:
|
229
236
|
return False, (
|
@@ -233,7 +240,7 @@ def _api_start(
|
|
233
240
|
f" - Ensure that '{instance_connector}' is available over HTTPS, " +
|
234
241
|
"and with `edit config`,\n" +
|
235
242
|
f" change the `protocol` for '{instance_connector}' to 'https'.\n\n" +
|
236
|
-
" - Run `edit config
|
243
|
+
" - Run `edit config api` and search for `permissions`.\n" +
|
237
244
|
" Under `api:permissions:chaining`, change the value of " +
|
238
245
|
"`insecure_parent_instance` to `true`,\n" +
|
239
246
|
" then restart the API process."
|
@@ -244,6 +251,7 @@ def _api_start(
|
|
244
251
|
'host': host,
|
245
252
|
'env_file': str(uvicorn_env_path.as_posix()),
|
246
253
|
'mrsm_instance': mrsm_instance,
|
254
|
+
'webterm_port': webterm_port,
|
247
255
|
'no_dash': no_dash,
|
248
256
|
'no_webterm': no_webterm or no_auth,
|
249
257
|
'no_auth': no_auth,
|
@@ -261,9 +269,22 @@ def _api_start(
|
|
261
269
|
uvicorn_config['use_colors'] = (not nopretty) if nopretty else ANSI
|
262
270
|
|
263
271
|
api_config['uvicorn'] = uvicorn_config
|
264
|
-
cf['
|
272
|
+
cf['api']['uvicorn'] = uvicorn_config
|
265
273
|
if secure:
|
266
|
-
cf['
|
274
|
+
cf['api']['permissions']['actions']['non_admin'] = False
|
275
|
+
|
276
|
+
if not uvicorn_config['no_webterm']:
|
277
|
+
from meerschaum._internal.term.tools import is_webterm_running
|
278
|
+
if webterm_port is None:
|
279
|
+
webterm_port = int(mrsm.get_config('api', 'webterm', 'port'))
|
280
|
+
if is_webterm_running(port=webterm_port):
|
281
|
+
return (
|
282
|
+
False,
|
283
|
+
(
|
284
|
+
f"Webterm is running on port {webterm_port}. "
|
285
|
+
"Start the API again with `--webterm-port`."
|
286
|
+
)
|
287
|
+
)
|
267
288
|
|
268
289
|
custom_keys = [
|
269
290
|
'mrsm_instance',
|
@@ -273,6 +294,7 @@ def _api_start(
|
|
273
294
|
'private',
|
274
295
|
'debug',
|
275
296
|
'production',
|
297
|
+
'webterm_port',
|
276
298
|
]
|
277
299
|
|
278
300
|
### write config to a temporary file to communicate with uvicorn threads
|
@@ -299,6 +321,7 @@ def _api_start(
|
|
299
321
|
MRSM_SERVER_ID: SERVER_ID,
|
300
322
|
MRSM_RUNTIME: 'api',
|
301
323
|
MRSM_CONFIG: json.loads(os.environ.get(MRSM_CONFIG, '{}')),
|
324
|
+
MRSM_ROOT_DIR: ROOT_DIR_PATH.as_posix(),
|
302
325
|
'FORWARDED_ALLOW_IPS': forwarded_allow_ips,
|
303
326
|
'TERM': os.environ.get('TERM', 'screen-256color'),
|
304
327
|
'SHELL': os.environ.get('SHELL', '/bin/bash'),
|
@@ -326,10 +349,10 @@ def _api_start(
|
|
326
349
|
env_text = ''
|
327
350
|
for key, val in env_dict.items():
|
328
351
|
value = str(
|
329
|
-
json.dumps(val, default=json_serialize_value)
|
352
|
+
json.dumps(val, default=json_serialize_value, separators=(',', ':'))
|
330
353
|
if isinstance(val, (dict))
|
331
354
|
else val
|
332
|
-
).replace('\\', '\\\\').replace("'", "
|
355
|
+
).replace('\\', '\\\\').replace("'", "\\'")
|
333
356
|
env_text += f"{key}='{value}'\n"
|
334
357
|
with open(uvicorn_env_path, 'w+', encoding='utf-8') as f:
|
335
358
|
if debug:
|
@@ -394,11 +417,16 @@ def _api_start(
|
|
394
417
|
except KeyboardInterrupt:
|
395
418
|
pass
|
396
419
|
|
420
|
+
old_stdin = sys.stdin
|
421
|
+
sys.stdin = None
|
422
|
+
|
397
423
|
if production:
|
398
424
|
_run_gunicorn()
|
399
425
|
else:
|
400
426
|
_run_uvicorn()
|
401
427
|
|
428
|
+
sys.stdin = old_stdin
|
429
|
+
|
402
430
|
### Cleanup
|
403
431
|
if uvicorn_config_path.parent.exists():
|
404
432
|
shutil.rmtree(uvicorn_config_path.parent)
|
meerschaum/actions/attach.py
CHANGED
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.
|