meerschaum 2.2.7__py3-none-any.whl → 2.3.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.
Files changed (70) hide show
  1. meerschaum/__init__.py +6 -1
  2. meerschaum/__main__.py +0 -5
  3. meerschaum/_internal/arguments/__init__.py +1 -1
  4. meerschaum/_internal/arguments/_parse_arguments.py +72 -6
  5. meerschaum/_internal/arguments/_parser.py +45 -15
  6. meerschaum/_internal/docs/index.py +265 -8
  7. meerschaum/_internal/entry.py +154 -24
  8. meerschaum/_internal/shell/Shell.py +264 -77
  9. meerschaum/actions/__init__.py +29 -17
  10. meerschaum/actions/api.py +12 -12
  11. meerschaum/actions/attach.py +113 -0
  12. meerschaum/actions/copy.py +68 -41
  13. meerschaum/actions/delete.py +112 -50
  14. meerschaum/actions/edit.py +3 -3
  15. meerschaum/actions/install.py +40 -32
  16. meerschaum/actions/pause.py +44 -27
  17. meerschaum/actions/restart.py +107 -0
  18. meerschaum/actions/show.py +130 -159
  19. meerschaum/actions/start.py +161 -100
  20. meerschaum/actions/stop.py +78 -42
  21. meerschaum/api/_events.py +25 -1
  22. meerschaum/api/_oauth2.py +2 -0
  23. meerschaum/api/_websockets.py +2 -2
  24. meerschaum/api/dash/callbacks/jobs.py +36 -44
  25. meerschaum/api/dash/jobs.py +89 -78
  26. meerschaum/api/routes/__init__.py +1 -0
  27. meerschaum/api/routes/_actions.py +148 -17
  28. meerschaum/api/routes/_jobs.py +407 -0
  29. meerschaum/api/routes/_pipes.py +5 -5
  30. meerschaum/config/_default.py +1 -0
  31. meerschaum/config/_jobs.py +1 -1
  32. meerschaum/config/_paths.py +7 -0
  33. meerschaum/config/_shell.py +8 -3
  34. meerschaum/config/_version.py +1 -1
  35. meerschaum/config/static/__init__.py +17 -0
  36. meerschaum/connectors/Connector.py +13 -7
  37. meerschaum/connectors/__init__.py +28 -15
  38. meerschaum/connectors/api/APIConnector.py +27 -1
  39. meerschaum/connectors/api/_actions.py +71 -6
  40. meerschaum/connectors/api/_jobs.py +368 -0
  41. meerschaum/connectors/api/_pipes.py +85 -84
  42. meerschaum/connectors/parse.py +27 -15
  43. meerschaum/core/Pipe/_bootstrap.py +16 -8
  44. meerschaum/jobs/_Executor.py +69 -0
  45. meerschaum/jobs/_Job.py +899 -0
  46. meerschaum/jobs/__init__.py +396 -0
  47. meerschaum/jobs/systemd.py +694 -0
  48. meerschaum/plugins/__init__.py +97 -12
  49. meerschaum/utils/daemon/Daemon.py +276 -30
  50. meerschaum/utils/daemon/FileDescriptorInterceptor.py +5 -5
  51. meerschaum/utils/daemon/RotatingFile.py +14 -7
  52. meerschaum/utils/daemon/StdinFile.py +121 -0
  53. meerschaum/utils/daemon/__init__.py +15 -7
  54. meerschaum/utils/daemon/_names.py +15 -13
  55. meerschaum/utils/formatting/__init__.py +2 -1
  56. meerschaum/utils/formatting/_jobs.py +115 -62
  57. meerschaum/utils/formatting/_shell.py +6 -0
  58. meerschaum/utils/misc.py +41 -22
  59. meerschaum/utils/packages/_packages.py +9 -6
  60. meerschaum/utils/process.py +9 -9
  61. meerschaum/utils/prompt.py +16 -8
  62. meerschaum/utils/venv/__init__.py +2 -2
  63. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/METADATA +22 -25
  64. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/RECORD +70 -61
  65. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/WHEEL +1 -1
  66. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/LICENSE +0 -0
  67. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/NOTICE +0 -0
  68. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/entry_points.txt +0 -0
  69. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/top_level.txt +0 -0
  70. {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/zip-safe +0 -0
meerschaum/actions/api.py CHANGED
@@ -10,12 +10,12 @@ import os
10
10
  from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
11
11
 
12
12
  def api(
13
- action: Optional[List[str]] = None,
14
- sysargs: Optional[List[str]] = None,
15
- debug: bool = False,
16
- mrsm_instance: Optional[str] = None,
17
- **kw: Any
18
- ) -> SuccessTuple:
13
+ action: Optional[List[str]] = None,
14
+ sysargs: Optional[List[str]] = None,
15
+ debug: bool = False,
16
+ mrsm_instance: Optional[str] = None,
17
+ **kw: Any
18
+ ) -> SuccessTuple:
19
19
  """
20
20
  Send commands to a Meerschaum WebAPI instance.
21
21
 
@@ -37,7 +37,8 @@ def api(
37
37
  """
38
38
  from meerschaum.utils.warnings import warn, info
39
39
  from meerschaum.utils.formatting import print_tuple
40
- from meerschaum.utils.packages import attempt_import
40
+ from meerschaum._internal.arguments._parse_arguments import parse_dict_to_sysargs
41
+
41
42
  if action is None:
42
43
  action = []
43
44
  if sysargs is None:
@@ -52,7 +53,6 @@ def api(
52
53
 
53
54
  from meerschaum.config import get_config
54
55
  from meerschaum.connectors import get_connector
55
- requests = attempt_import('requests')
56
56
  if debug:
57
57
  from meerschaum.utils.formatting import pprint
58
58
  api_configs = get_config('meerschaum', 'connectors', 'api', patch=True)
@@ -68,12 +68,13 @@ def api(
68
68
  del action[0]
69
69
  if len(args_to_send) > 1:
70
70
  del args_to_send[0]
71
+
71
72
  kw['action'] = action
72
73
  kw['debug'] = debug
73
74
  kw['sysargs'] = args_to_send
74
75
  kw['yes'] = True
75
76
 
76
- api_conn = get_connector(type='api', label=api_label)
77
+ api_conn = get_connector(f'api:{api_label}')
77
78
 
78
79
  if mrsm_instance is not None and str(mrsm_instance) == str(api_conn):
79
80
  warn(
@@ -83,9 +84,8 @@ def api(
83
84
  elif mrsm_instance is not None:
84
85
  kw['mrsm_instance'] = str(mrsm_instance)
85
86
 
86
- success, message = api_conn.do_action(**kw)
87
- print_tuple((success, message), common_only=True)
88
- msg = f"Action " + ('succeeded' if success else 'failed') + " with message:\n" + str(message)
87
+ sysargs = parse_dict_to_sysargs(kw)
88
+ success, message = api_conn.do_action(sysargs)
89
89
  return success, message
90
90
 
91
91
  def _api_start(
@@ -0,0 +1,113 @@
1
+ #! /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # vim:fenc=utf-8
4
+
5
+ """
6
+ Attach to running jobs.
7
+ """
8
+
9
+ import meerschaum as mrsm
10
+ from meerschaum.utils.typing import Optional, List, Any, SuccessTuple
11
+
12
+ def attach(
13
+ action: Optional[List[str]] = None,
14
+ executor_keys: Optional[str] = None,
15
+ **kwargs: Any
16
+ ) -> SuccessTuple:
17
+ """
18
+ Attach to a job, and prompt the user when blocking on input.
19
+ """
20
+ from meerschaum.actions import choose_subaction
21
+ attach_options = {
22
+ 'jobs': _attach_jobs,
23
+ 'logs': _attach_logs,
24
+ }
25
+ return choose_subaction(action, attach_options, executor_keys=executor_keys, **kwargs)
26
+
27
+
28
+ def _complete_attach(
29
+ action: Optional[List[str]] = None,
30
+ **kw: Any
31
+ ) -> List[str]:
32
+ """
33
+ Override the default Meerschaum `complete_` function.
34
+ """
35
+ from meerschaum.actions.delete import _complete_delete_jobs
36
+
37
+ if action is None:
38
+ action = []
39
+
40
+ options = {
41
+ 'job': _complete_delete_jobs,
42
+ 'jobs': _complete_delete_jobs,
43
+ 'log': _complete_delete_jobs,
44
+ 'logs': _complete_delete_jobs,
45
+ }
46
+
47
+ if (
48
+ len(action) > 0 and action[0] in options
49
+ and kw.get('line', '').split(' ')[-1] != action[0]
50
+ ):
51
+ sub = action[0]
52
+ del action[0]
53
+ return options[sub](action=action, **kw)
54
+
55
+ from meerschaum._internal.shell import default_action_completer
56
+ return default_action_completer(action=(['attach'] + action), **kw)
57
+
58
+
59
+ def _attach_jobs(
60
+ action: Optional[List[str]] = None,
61
+ name: Optional[str] = None,
62
+ executor_keys: Optional[str] = None,
63
+ **kwargs: Any
64
+ ) -> SuccessTuple:
65
+ """
66
+ Attach to a job, and prompt the user when blocking on input.
67
+ """
68
+ action = action or []
69
+ if not action and not name:
70
+ return False, "Provide the name of the job to attach to."
71
+
72
+ name = name or action[0]
73
+ job = mrsm.Job(name, executor_keys=executor_keys)
74
+ other_executor_keys = 'systemd' if executor_keys in (None, 'local') else 'local'
75
+ if not job.exists():
76
+ other_job = mrsm.Job(name, executor_keys=other_executor_keys)
77
+ if not other_job.exists():
78
+ return False, f"Job '{job.name}' does not exist."
79
+
80
+ job = other_job
81
+
82
+ success, message = True, "Success"
83
+
84
+ def _capture_result(result: SuccessTuple):
85
+ nonlocal success, message
86
+ success, message = result
87
+
88
+ try:
89
+ job.monitor_logs(
90
+ stop_callback_function=_capture_result,
91
+ accept_input=True,
92
+ stop_on_exit=True,
93
+ strip_timestamps=True,
94
+ )
95
+ except KeyboardInterrupt:
96
+ pass
97
+
98
+ return success, message
99
+
100
+
101
+ def _attach_logs(*args, **kwargs) -> SuccessTuple:
102
+ """
103
+ Attach to jobs' logs.
104
+ """
105
+ from meerschaum.actions.show import _show_logs
106
+ return _show_logs(*args, **kwargs)
107
+
108
+
109
+ ### NOTE: This must be the final statement of the module.
110
+ ### Any subactions added below these lines will not
111
+ ### be added to the `help` docstring.
112
+ from meerschaum.actions import choices_docstring as _choices_docstring
113
+ attach.__doc__ += _choices_docstring('attach')
@@ -10,9 +10,9 @@ from __future__ import annotations
10
10
  from meerschaum.utils.typing import Union, Any, Sequence, SuccessTuple, Optional, Tuple, List
11
11
 
12
12
  def copy(
13
- action: Optional[List[str]] = None,
14
- **kw : Any
15
- ) -> SuccessTuple:
13
+ action: Optional[List[str]] = None,
14
+ **kw : Any
15
+ ) -> SuccessTuple:
16
16
  """
17
17
  Duplicate connectors or pipes.
18
18
 
@@ -32,17 +32,16 @@ def copy(
32
32
 
33
33
 
34
34
  def _complete_copy(
35
- action : Optional[List[str]] = None,
36
- **kw : Any
37
- ) -> List[str]:
35
+ action: Optional[List[str]] = None,
36
+ **kw: Any
37
+ ) -> List[str]:
38
38
  """
39
39
  Override the default Meerschaum `complete_` function.
40
-
41
40
  """
42
- from meerschaum.actions.start import _complete_start_jobs
43
41
  from meerschaum.actions.edit import _complete_edit_config
44
42
  if action is None:
45
43
  action = []
44
+
46
45
  options = {
47
46
  'connector': _complete_copy_connectors,
48
47
  'connectors': _complete_copy_connectors,
@@ -61,15 +60,14 @@ def _complete_copy(
61
60
 
62
61
 
63
62
  def _copy_pipes(
64
- yes: bool = False,
65
- noask: bool = False,
66
- force: bool = False,
67
- debug: bool = False,
68
- **kw
69
- ) -> SuccessTuple:
63
+ yes: bool = False,
64
+ noask: bool = False,
65
+ force: bool = False,
66
+ debug: bool = False,
67
+ **kw
68
+ ) -> SuccessTuple:
70
69
  """
71
70
  Copy pipes' attributes and make new pipes.
72
-
73
71
  """
74
72
  from meerschaum import get_pipes, Pipe
75
73
  from meerschaum.utils.prompt import prompt, yes_no
@@ -132,16 +130,15 @@ def _copy_pipes(
132
130
 
133
131
  return successes > 0, msg
134
132
 
133
+
135
134
  def _copy_connectors(
136
- action: Optional[List[str]] = None,
137
- connector_keys: Optional[List[str]] = None,
138
- nopretty: bool = False,
139
- yes: bool = False,
140
- force: bool = False,
141
- noask: bool = False,
142
- debug: bool = False,
143
- **kw
144
- ) -> SuccessTuple:
135
+ action: Optional[List[str]] = None,
136
+ connector_keys: Optional[List[str]] = None,
137
+ nopretty: bool = False,
138
+ force: bool = False,
139
+ debug: bool = False,
140
+ **kwargs: Any
141
+ ) -> SuccessTuple:
145
142
  """
146
143
  Create a new connector from an existing one.
147
144
 
@@ -153,39 +150,69 @@ def _copy_connectors(
153
150
  from meerschaum.config._edit import write_config
154
151
  from meerschaum.utils.warnings import info, warn
155
152
  from meerschaum.utils.formatting import pprint
153
+ from meerschaum.actions import get_action
156
154
  cf = _config()
157
155
  if action is None:
158
156
  action = []
159
157
  if connector_keys is None:
160
158
  connector_keys = []
161
159
 
162
- _keys = list(set(action + connector_keys))
160
+ _keys = (action or []) + connector_keys
163
161
 
164
162
  if not _keys:
165
163
  return False, "No connectors to copy."
166
164
 
167
- for ck in _keys:
168
- try:
169
- conn = parse_connector_keys(ck)
170
- except Exception as e:
171
- warn(f"Unable to parse connector '{ck}'. Skipping...", stack=False)
172
- continue
165
+ if len(_keys) < 1 or len(_keys) > 2:
166
+ return False, "Provide one set of connector keys."
173
167
 
174
- attrs = get_config('meerschaum', 'connectors', conn.type, conn.label)
175
- pprint(attrs, nopretty=nopretty)
168
+ ck = _keys[0]
176
169
 
177
- asking = True
178
- # while asking:
179
- # new_ck = prompt("Please enter a new label for the new connector ():")
170
+ try:
171
+ conn = parse_connector_keys(ck)
172
+ except Exception as e:
173
+ return False, f"Unable to parse connector '{ck}'."
180
174
 
175
+ if len(_keys) == 2:
176
+ new_ck = _keys[1] if ':' in _keys[1] else None
177
+ new_label = _keys[1].split(':')[-1]
178
+ else:
179
+ new_ck = None
180
+ new_label = None
181
+
182
+ try:
183
+ if new_label is None:
184
+ new_label = prompt(f"Enter a label for the new '{conn.type}' connector:")
185
+ except KeyboardInterrupt:
186
+ return False, "Nothing was copied."
187
+
188
+ if new_ck is None:
189
+ new_ck = f"{conn.type}:{new_label}"
190
+
191
+ info(f"Registering connector '{new_ck}' from '{ck}'...")
192
+
193
+ attrs = get_config('meerschaum', 'connectors', conn.type, conn.label)
194
+ pprint(attrs, nopretty=nopretty)
195
+ if not force and not yes_no(
196
+ f"Register connector '{new_ck}' with the above attributes?",
197
+ default='n',
198
+ **kwargs
199
+ ):
200
+ return False, "Nothing was copied."
201
+
202
+ register_connector = get_action(['register', 'connector'])
203
+ register_success, register_msg = register_connector(
204
+ [new_ck],
205
+ params=attrs,
206
+ **kwargs
207
+ )
208
+ return register_success, register_msg
181
209
 
182
- return False, "Not implemented."
183
210
 
184
211
  def _complete_copy_connectors(
185
- action : Optional[List[str]] = None,
186
- line : str = '',
187
- **kw : Any
188
- ) -> List[str]:
212
+ action: Optional[List[str]] = None,
213
+ line: str = '',
214
+ **kw: Any
215
+ ) -> List[str]:
189
216
  from meerschaum.config import get_config
190
217
  from meerschaum.utils.misc import get_connector_labels
191
218
  types = list(get_config('meerschaum', 'connectors').keys())
@@ -10,9 +10,9 @@ from __future__ import annotations
10
10
  from meerschaum.utils.typing import Any, SuccessTuple, Union, Optional, List
11
11
 
12
12
  def delete(
13
- action: Optional[List[str]] = None,
14
- **kw: Any
15
- ) -> SuccessTuple:
13
+ action: Optional[List[str]] = None,
14
+ **kw: Any
15
+ ) -> SuccessTuple:
16
16
  """
17
17
  Delete an element.
18
18
 
@@ -35,23 +35,21 @@ def delete(
35
35
 
36
36
 
37
37
  def _complete_delete(
38
- action: Optional[List[str]] = None,
39
- **kw: Any
40
- ) -> List[str]:
38
+ action: Optional[List[str]] = None,
39
+ **kw: Any
40
+ ) -> List[str]:
41
41
  """
42
42
  Override the default Meerschaum `complete_` function.
43
-
44
43
  """
45
- from meerschaum.actions.start import _complete_start_jobs
46
44
  from meerschaum.actions.edit import _complete_edit_config
47
45
  if action is None:
48
46
  action = []
49
47
  options = {
50
48
  'connector': _complete_delete_connectors,
51
49
  'connectors': _complete_delete_connectors,
52
- 'config' : _complete_edit_config,
53
- 'job' : _complete_start_jobs,
54
- 'jobs' : _complete_start_jobs,
50
+ 'config': _complete_edit_config,
51
+ 'job': _complete_delete_jobs,
52
+ 'jobs': _complete_delete_jobs,
55
53
  }
56
54
 
57
55
  if (
@@ -390,22 +388,27 @@ def _complete_delete_connectors(
390
388
 
391
389
 
392
390
  def _delete_jobs(
393
- action: Optional[List[str]] = None,
394
- noask: bool = False,
395
- nopretty: bool = False,
396
- force: bool = False,
397
- yes: bool = False,
398
- debug: bool = False,
399
- **kw
400
- ) -> SuccessTuple:
391
+ action: Optional[List[str]] = None,
392
+ executor_keys: Optional[str] = None,
393
+ noask: bool = False,
394
+ nopretty: bool = False,
395
+ force: bool = False,
396
+ yes: bool = False,
397
+ debug: bool = False,
398
+ **kw
399
+ ) -> SuccessTuple:
401
400
  """
402
401
  Remove a job's log files and delete the job's ID.
403
402
 
404
403
  If the job is running, ask to kill the job first.
405
404
 
406
405
  """
407
- from meerschaum.utils.daemon import (
408
- Daemon, get_running_daemons, get_stopped_daemons, get_filtered_daemons, get_paused_daemons
406
+ from meerschaum.jobs import (
407
+ Job,
408
+ get_running_jobs,
409
+ get_stopped_jobs,
410
+ get_filtered_jobs,
411
+ get_paused_jobs,
409
412
  )
410
413
  from meerschaum.utils.prompt import yes_no
411
414
  from meerschaum.utils.formatting._jobs import pprint_jobs
@@ -413,49 +416,53 @@ def _delete_jobs(
413
416
  from meerschaum.utils.warnings import warn
414
417
  from meerschaum.utils.misc import items_str
415
418
  from meerschaum.actions import actions
416
- daemons = get_filtered_daemons(action, warn=(not nopretty))
417
- if not daemons:
419
+
420
+ jobs = get_filtered_jobs(executor_keys, action, debug=debug)
421
+ if not jobs:
418
422
  return True, "No jobs to delete; nothing to do."
419
423
 
420
424
  _delete_all_jobs = False
421
425
  if not action:
422
426
  if not force:
423
- pprint_jobs(daemons)
427
+ pprint_jobs(jobs)
424
428
  if not yes_no(
425
429
  "Delete all jobs? This cannot be undone!",
426
430
  noask=noask, yes=yes, default='n'
427
431
  ):
428
432
  return False, "No jobs were deleted."
433
+
429
434
  _delete_all_jobs = True
430
- _running_daemons = get_running_daemons(daemons)
431
- _paused_daemons = get_paused_daemons(daemons)
432
- _stopped_daemons = get_stopped_daemons(daemons)
433
- _to_delete = _stopped_daemons
434
435
 
435
- to_stop_daemons = _running_daemons + _paused_daemons
436
- if to_stop_daemons:
436
+ _running_jobs = get_running_jobs(executor_keys, jobs, debug=debug)
437
+ _paused_jobs = get_paused_jobs(executor_keys, jobs, debug=debug)
438
+ _stopped_jobs = get_stopped_jobs(executor_keys, jobs, debug=debug)
439
+ _to_delete = _stopped_jobs
440
+
441
+ to_stop_jobs = {**_running_jobs, **_paused_jobs}
442
+ if to_stop_jobs:
437
443
  clear_screen(debug=debug)
438
444
  if not force:
439
- pprint_jobs(to_stop_daemons, nopretty=nopretty)
445
+ pprint_jobs(to_stop_jobs, nopretty=nopretty)
440
446
  if force or yes_no(
441
447
  "Stop these jobs?",
442
448
  default='n', yes=yes, noask=noask
443
449
  ):
444
450
  actions['stop'](
445
- action = (['jobs'] + [d.daemon_id for d in to_stop_daemons]),
446
- nopretty = nopretty,
447
- yes = yes,
448
- force = force,
449
- noask = noask,
450
- debug = debug,
451
+ action=(['jobs'] + [_name for _name in to_stop_jobs]),
452
+ executor_keys=executor_keys,
453
+ nopretty=nopretty,
454
+ yes=yes,
455
+ force=force,
456
+ noask=noask,
457
+ debug=debug,
451
458
  **kw
452
459
  )
453
460
  ### Ensure the running jobs are dead.
454
- if get_running_daemons(daemons):
461
+ if get_running_jobs(executor_keys, jobs, debug=debug):
455
462
  return False, (
456
463
  f"Failed to kill running jobs. Please stop these jobs before deleting."
457
464
  )
458
- _to_delete += to_stop_daemons
465
+ _to_delete.update(to_stop_jobs)
459
466
 
460
467
  ### User decided not to kill running jobs.
461
468
  else:
@@ -473,26 +480,81 @@ def _delete_jobs(
473
480
  return False, "No jobs were deleted."
474
481
 
475
482
  _deleted = []
476
- for d in _to_delete:
477
- d.cleanup()
478
- if d.path.exists() and not nopretty:
479
- warn(f"Failed to delete job '{d.daemon_id}'.", stack=False)
483
+ for name, job in _to_delete.items():
484
+ delete_success, delete_msg = job.delete()
485
+ if not delete_success:
486
+ warn(f"Failed to delete job '{name}'.", stack=False)
480
487
  continue
481
- _deleted.append(d)
488
+ _deleted.append(name)
482
489
 
483
490
  return (
484
491
  len(_deleted) > 0,
485
492
  ("Deleted job" + ("s" if len(_deleted) != 1 else '')
486
- + f" {items_str([d.daemon_id for d in _deleted])}."),
493
+ + f" {items_str([_name for _name in _deleted])}."),
487
494
  )
488
495
 
489
496
 
497
+ def _complete_delete_jobs(
498
+ action: Optional[List[str]] = None,
499
+ executor_keys: Optional[str] = None,
500
+ line: str = '',
501
+ _get_job_method: Optional[str, List[str]] = None,
502
+ **kw
503
+ ) -> List[str]:
504
+ from meerschaum._internal.shell.Shell import shell_attrs
505
+ from meerschaum.jobs import (
506
+ get_jobs,
507
+ get_filtered_jobs,
508
+ get_restart_jobs,
509
+ get_stopped_jobs,
510
+ get_paused_jobs,
511
+ get_running_jobs,
512
+ get_executor_keys_from_context,
513
+ )
514
+ from meerschaum.utils.misc import remove_ansi
515
+ from meerschaum.connectors.parse import parse_executor_keys
516
+
517
+ executor_keys = (
518
+ executor_keys
519
+ or remove_ansi(
520
+ shell_attrs.get('executor_keys', get_executor_keys_from_context())
521
+ )
522
+ )
523
+
524
+ if parse_executor_keys(executor_keys, construct=False) is None:
525
+ return []
526
+
527
+ jobs = get_jobs(executor_keys, include_hidden=False)
528
+ if _get_job_method:
529
+ method_keys = [_get_job_method] if isinstance(_get_job_method, str) else _get_job_method
530
+ method_jobs = {}
531
+ for method_key in method_keys:
532
+ method_func = locals()[f'get_{method_key}_jobs']
533
+ method_jobs.update(method_func(jobs=jobs))
534
+ jobs = method_jobs
535
+
536
+ if not action:
537
+ return list(jobs)
538
+
539
+ possibilities = []
540
+ _line_end = line.split(' ')[-1]
541
+ for name in jobs:
542
+ if name in action:
543
+ continue
544
+ if _line_end == '':
545
+ possibilities.append(name)
546
+ continue
547
+ if name.startswith(action[-1]):
548
+ possibilities.append(name)
549
+ return possibilities
550
+
551
+
490
552
  def _delete_venvs(
491
- action: Optional[List[str]] = None,
492
- yes: bool = False,
493
- force: bool = False,
494
- **kwargs: Any
495
- ) -> SuccessTuple:
553
+ action: Optional[List[str]] = None,
554
+ yes: bool = False,
555
+ force: bool = False,
556
+ **kwargs: Any
557
+ ) -> SuccessTuple:
496
558
  """
497
559
  Remove virtual environments.
498
560
  Specify which venvs to remove, or remove everything at once.
@@ -11,9 +11,9 @@ import meerschaum as mrsm
11
11
  from meerschaum.utils.typing import List, Any, SuccessTuple, Optional, Dict
12
12
 
13
13
  def edit(
14
- action: Optional[List[str]] = None,
15
- **kw: Any
16
- ) -> SuccessTuple:
14
+ action: Optional[List[str]] = None,
15
+ **kw: Any
16
+ ) -> SuccessTuple:
17
17
  """
18
18
  Edit an existing element.
19
19
  """