meerschaum 2.2.6__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 (80) hide show
  1. meerschaum/__init__.py +6 -1
  2. meerschaum/__main__.py +9 -9
  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 +167 -37
  8. meerschaum/_internal/shell/Shell.py +290 -99
  9. meerschaum/_internal/shell/updates.py +175 -0
  10. meerschaum/actions/__init__.py +29 -17
  11. meerschaum/actions/api.py +12 -12
  12. meerschaum/actions/attach.py +113 -0
  13. meerschaum/actions/copy.py +68 -41
  14. meerschaum/actions/delete.py +112 -50
  15. meerschaum/actions/edit.py +3 -3
  16. meerschaum/actions/install.py +40 -32
  17. meerschaum/actions/pause.py +44 -27
  18. meerschaum/actions/register.py +19 -5
  19. meerschaum/actions/restart.py +107 -0
  20. meerschaum/actions/show.py +130 -159
  21. meerschaum/actions/start.py +161 -100
  22. meerschaum/actions/stop.py +78 -42
  23. meerschaum/actions/sync.py +3 -3
  24. meerschaum/actions/upgrade.py +28 -36
  25. meerschaum/api/_events.py +25 -1
  26. meerschaum/api/_oauth2.py +2 -0
  27. meerschaum/api/_websockets.py +2 -2
  28. meerschaum/api/dash/callbacks/jobs.py +36 -44
  29. meerschaum/api/dash/jobs.py +89 -78
  30. meerschaum/api/routes/__init__.py +1 -0
  31. meerschaum/api/routes/_actions.py +148 -17
  32. meerschaum/api/routes/_jobs.py +407 -0
  33. meerschaum/api/routes/_pipes.py +25 -25
  34. meerschaum/config/_default.py +1 -0
  35. meerschaum/config/_formatting.py +1 -0
  36. meerschaum/config/_jobs.py +1 -1
  37. meerschaum/config/_paths.py +11 -0
  38. meerschaum/config/_shell.py +84 -67
  39. meerschaum/config/_version.py +1 -1
  40. meerschaum/config/static/__init__.py +18 -0
  41. meerschaum/connectors/Connector.py +13 -7
  42. meerschaum/connectors/__init__.py +28 -15
  43. meerschaum/connectors/api/APIConnector.py +27 -1
  44. meerschaum/connectors/api/_actions.py +71 -6
  45. meerschaum/connectors/api/_jobs.py +368 -0
  46. meerschaum/connectors/api/_misc.py +1 -1
  47. meerschaum/connectors/api/_pipes.py +85 -84
  48. meerschaum/connectors/api/_request.py +13 -9
  49. meerschaum/connectors/parse.py +27 -15
  50. meerschaum/core/Pipe/_bootstrap.py +16 -8
  51. meerschaum/core/Pipe/_sync.py +3 -0
  52. meerschaum/jobs/_Executor.py +69 -0
  53. meerschaum/jobs/_Job.py +899 -0
  54. meerschaum/jobs/__init__.py +396 -0
  55. meerschaum/jobs/systemd.py +694 -0
  56. meerschaum/plugins/__init__.py +97 -12
  57. meerschaum/utils/daemon/Daemon.py +352 -147
  58. meerschaum/utils/daemon/FileDescriptorInterceptor.py +19 -10
  59. meerschaum/utils/daemon/RotatingFile.py +22 -8
  60. meerschaum/utils/daemon/StdinFile.py +121 -0
  61. meerschaum/utils/daemon/__init__.py +42 -27
  62. meerschaum/utils/daemon/_names.py +15 -13
  63. meerschaum/utils/formatting/__init__.py +83 -37
  64. meerschaum/utils/formatting/_jobs.py +146 -55
  65. meerschaum/utils/formatting/_shell.py +6 -0
  66. meerschaum/utils/misc.py +41 -22
  67. meerschaum/utils/packages/__init__.py +21 -15
  68. meerschaum/utils/packages/_packages.py +9 -6
  69. meerschaum/utils/process.py +9 -9
  70. meerschaum/utils/prompt.py +20 -7
  71. meerschaum/utils/schedule.py +21 -15
  72. meerschaum/utils/venv/__init__.py +2 -2
  73. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/METADATA +22 -25
  74. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/RECORD +80 -70
  75. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/WHEEL +1 -1
  76. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/LICENSE +0 -0
  77. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/NOTICE +0 -0
  78. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/entry_points.txt +0 -0
  79. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/top_level.txt +0 -0
  80. {meerschaum-2.2.6.dist-info → meerschaum-2.3.0.dist-info}/zip-safe +0 -0
@@ -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
  """
@@ -10,9 +10,9 @@ from __future__ import annotations
10
10
  from meerschaum.utils.typing import List, Any, SuccessTuple, Optional, Union
11
11
 
12
12
  def install(
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
  Install Meerschaum plugins or Python packages.
18
18
  """
@@ -26,9 +26,9 @@ def install(
26
26
 
27
27
 
28
28
  def _complete_install(
29
- action: Optional[List[str]] = None,
30
- **kw: Any
31
- ) -> List[str]:
29
+ action: Optional[List[str]] = None,
30
+ **kw: Any
31
+ ) -> List[str]:
32
32
  """
33
33
  Override the default Meerschaum `complete_` function.
34
34
  """
@@ -52,13 +52,13 @@ def _complete_install(
52
52
 
53
53
 
54
54
  def _install_plugins(
55
- action: Optional[List[str]] = None,
56
- repository: Optional[str] = None,
57
- skip_deps: bool = False,
58
- force: bool = False,
59
- debug: bool = False,
60
- **kw: Any
61
- ) -> SuccessTuple:
55
+ action: Optional[List[str]] = None,
56
+ repository: Optional[str] = None,
57
+ skip_deps: bool = False,
58
+ force: bool = False,
59
+ debug: bool = False,
60
+ **kw: Any
61
+ ) -> SuccessTuple:
62
62
  """
63
63
  Install a plugin.
64
64
 
@@ -103,10 +103,10 @@ def _install_plugins(
103
103
 
104
104
 
105
105
  def _complete_install_plugins(
106
- action: Optional[List[str]] = None,
107
- repository: Optional[str] = None,
108
- **kw: Any
109
- ) -> List[str]:
106
+ action: Optional[List[str]] = None,
107
+ repository: Optional[str] = None,
108
+ **kw: Any
109
+ ) -> List[str]:
110
110
  """
111
111
  Search for plugins to autocomplete command line text.
112
112
  NOTE: Disabled for the time being so we don't interrupt the user typing.
@@ -143,12 +143,12 @@ class NoVenv:
143
143
  pass
144
144
 
145
145
  def _install_packages(
146
- action: Optional[List[str]] = None,
147
- sub_args: Optional[List[str]] = None,
148
- venv: Union[str, NoVenv] = NoVenv,
149
- debug: bool = False,
150
- **kw: Any
151
- ) -> SuccessTuple:
146
+ action: Optional[List[str]] = None,
147
+ sub_args: Optional[List[str]] = None,
148
+ venv: Union[str, NoVenv] = NoVenv,
149
+ debug: bool = False,
150
+ **kw: Any
151
+ ) -> SuccessTuple:
152
152
  """
153
153
  Install PyPI packages into the Meerschaum virtual environment.
154
154
 
@@ -179,19 +179,17 @@ def _install_packages(
179
179
  )
180
180
 
181
181
 
182
- def _complete_install_packages(
183
- **kw : Any
184
- ) -> List[str]:
182
+ def _complete_install_packages(**kw : Any) -> List[str]:
185
183
  return []
186
184
 
187
185
 
188
186
  def _install_required(
189
- action: Optional[List[str]] = None,
190
- repository: Optional[str] = None,
191
- force: bool = False,
192
- debug: bool = False,
193
- **kw
194
- ) -> SuccessTuple:
187
+ action: Optional[List[str]] = None,
188
+ repository: Optional[str] = None,
189
+ force: bool = False,
190
+ debug: bool = False,
191
+ **kw
192
+ ) -> SuccessTuple:
195
193
  """
196
194
  Install the required packages for Meerschaum plugins.
197
195
  Each plugin's packages will be installed into its virtual environment.
@@ -237,6 +235,16 @@ def _complete_install_required(*args, **kw) -> List[str]:
237
235
  return _complete_uninstall_plugins(*args, **kw)
238
236
 
239
237
 
238
+ def _install_systemd(
239
+ action: Optional[List[str]] = None,
240
+ **kwargs: Any
241
+ ) -> SuccessTuple:
242
+ """
243
+ Install the Meerschaum job monitor as a systemd service.
244
+ """
245
+ import sys
246
+
247
+
240
248
  ### NOTE: This must be the final statement of the module.
241
249
  ### Any subactions added below these lines will not
242
250
  ### be added to the `help` docstring.
@@ -27,13 +27,20 @@ def _complete_pause(
27
27
  """
28
28
  Override the default Meerschaum `complete_` function.
29
29
  """
30
- from meerschaum.actions.start import _complete_start_jobs
30
+ from meerschaum.actions.delete import _complete_delete_jobs
31
+ from functools import partial
32
+
31
33
  if action is None:
32
34
  action = []
33
35
 
36
+ _complete_pause_jobs = partial(
37
+ _complete_delete_jobs,
38
+ _get_job_method='running',
39
+ )
40
+
34
41
  options = {
35
- 'job' : _complete_start_jobs,
36
- 'jobs' : _complete_start_jobs,
42
+ 'job': _complete_pause_jobs,
43
+ 'jobs': _complete_pause_jobs,
37
44
  }
38
45
 
39
46
  if (
@@ -49,43 +56,53 @@ def _complete_pause(
49
56
 
50
57
 
51
58
  def _pause_jobs(
52
- action: Optional[List[str]] = None,
53
- noask: bool = False,
54
- force: bool = False,
55
- yes: bool = False,
56
- nopretty: bool = False,
57
- **kw
58
- ) -> SuccessTuple:
59
+ action: Optional[List[str]] = None,
60
+ executor_keys: Optional[str] = None,
61
+ noask: bool = False,
62
+ force: bool = False,
63
+ yes: bool = False,
64
+ nopretty: bool = False,
65
+ debug: bool = False,
66
+ **kw
67
+ ) -> SuccessTuple:
59
68
  """
60
- Pause running jobs that were started with `-d` or `start job`.
61
-
62
- To see running jobs, run `show jobs`.
69
+ Pause (suspend) running jobs.
63
70
  """
64
71
  from meerschaum.utils.formatting._jobs import pprint_jobs
65
72
  from meerschaum.utils.daemon import (
66
73
  get_filtered_daemons, get_running_daemons, get_stopped_daemons, get_paused_daemons,
67
74
  )
75
+ from meerschaum.jobs import (
76
+ get_filtered_jobs,
77
+ get_running_jobs,
78
+ get_stopped_jobs,
79
+ get_paused_jobs,
80
+ )
68
81
  from meerschaum.utils.warnings import warn
69
82
  from meerschaum.utils.prompt import yes_no
70
83
  from meerschaum.utils.misc import items_str
71
- daemons = get_filtered_daemons(action, warn=(not nopretty))
72
- _running_daemons = get_running_daemons(daemons)
73
- _paused_daemons = get_paused_daemons(daemons)
74
- _stopped_daemons = get_stopped_daemons(daemons)
75
- if action and _stopped_daemons and not nopretty:
84
+
85
+ jobs = get_filtered_jobs(executor_keys, action, debug=debug, warn=(not nopretty))
86
+ running_jobs = get_running_jobs(executor_keys, jobs, debug=debug)
87
+ paused_jobs = get_paused_jobs(executor_keys, jobs, debug=debug)
88
+ stopped_jobs = get_stopped_jobs(executor_keys, jobs, debug=debug)
89
+
90
+ if action and stopped_jobs and not nopretty:
76
91
  warn(
77
- f"Skipping stopped job" + ("s" if len(_stopped_daemons) > 1 else '') + " '" +
78
- ("', '".join(d.daemon_id for d in _stopped_daemons)) + "'.",
79
- stack = False
92
+ f"Skipping stopped job" + ("s" if len(stopped_jobs) > 1 else '')
93
+ + " '"
94
+ + ("', '".join(stopped_jobs.keys()))
95
+ + "'.",
96
+ stack=False,
80
97
  )
81
98
 
82
- daemons_to_pause = _running_daemons + _paused_daemons
83
- if not daemons_to_pause:
99
+ jobs_to_pause = {**running_jobs, **paused_jobs}
100
+ if not jobs_to_pause:
84
101
  return False, "No running jobs to pause. You can start jobs with `-d` or `start jobs`."
85
102
 
86
103
  if not action:
87
104
  if not force:
88
- pprint_jobs(_running_daemons)
105
+ pprint_jobs(running_jobs)
89
106
  if not yes_no(
90
107
  "Pause all running jobs?",
91
108
  noask=noask, yes=yes, default='n'
@@ -93,9 +110,9 @@ def _pause_jobs(
93
110
  return False, "No jobs were paused."
94
111
 
95
112
  successes, fails = [], []
96
- for d in daemons_to_pause:
97
- pause_success, pause_msg = d.pause()
98
- (successes if pause_success else fails).append(d.daemon_id)
113
+ for name, job in jobs_to_pause.items():
114
+ pause_success, pause_msg = job.pause()
115
+ (successes if pause_success else fails).append(name)
99
116
 
100
117
  msg = (
101
118
  (
@@ -203,14 +203,23 @@ def _register_plugins(
203
203
  successes = {}
204
204
 
205
205
  for name, plugin in plugins_to_register.items():
206
- desc = None
207
206
  plugin.attributes = repo_connector.get_plugin_attributes(plugin, debug=debug)
208
207
  if plugin.attributes is None:
209
208
  plugin.attributes = {}
209
+
210
+ try:
211
+ description_text = plugin.attributes.get('description', '')
212
+ doc_text = plugin.module.__doc__.lstrip().rstrip()
213
+ except Exception:
214
+ description_text = ''
215
+ doc_text = ''
216
+
217
+ desc = description_text or doc_text or ''
218
+
210
219
  question = f"Would you like to add a description to plugin '{name}'?"
211
- if plugin.attributes.get('description', None):
220
+ if desc:
212
221
  info(f"Found existing description for plugin '{plugin}':")
213
- print(plugin.attributes['description'])
222
+ print(desc)
214
223
  question = (
215
224
  "Would you like to overwrite this description?\n"
216
225
  + "To edit the existing text, visit /dash/plugins for this repository."
@@ -220,9 +229,14 @@ def _register_plugins(
220
229
  default='n',
221
230
  yes=yes
222
231
  ):
223
- info('Press (Esc + Enter) to submit the description, (CTRL + C) to cancel.')
232
+ info('Press (Esc + Enter) to submit, (CTRL + C) to cancel.')
224
233
  try:
225
- desc = prompt('', multiline=True, icon=False)
234
+ desc = prompt(
235
+ '',
236
+ multiline=True,
237
+ icon=False,
238
+ default_editable=desc.lstrip().rstrip(),
239
+ )
226
240
  except KeyboardInterrupt:
227
241
  desc = None
228
242
  if desc == '':
@@ -0,0 +1,107 @@
1
+ #! /usr/bin/env python3
2
+ # vim:fenc=utf-8
3
+
4
+ """
5
+ Restart stopped jobs which have not been manually stopped.
6
+ """
7
+
8
+ from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
9
+
10
+ def restart(
11
+ action: Optional[List[str]] = None,
12
+ executor_keys: Optional[str] = None,
13
+ **kwargs: Any
14
+ ) -> SuccessTuple:
15
+ """
16
+ Restart stopped jobs which have not been manually stopped.
17
+ """
18
+ from meerschaum.actions import choose_subaction
19
+ attach_options = {
20
+ 'jobs': _restart_jobs,
21
+ }
22
+ return choose_subaction(action, attach_options, executor_keys=executor_keys, **kwargs)
23
+
24
+
25
+ def _complete_restart(
26
+ action: Optional[List[str]] = None,
27
+ **kw: Any
28
+ ) -> List[str]:
29
+ """
30
+ Override the default Meerschaum `complete_` function.
31
+ """
32
+ from functools import partial
33
+ from meerschaum.actions.delete import _complete_delete_jobs
34
+
35
+ if action is None:
36
+ action = []
37
+
38
+ _complete_restart_jobs = partial(
39
+ _complete_delete_jobs,
40
+ _get_job_method='restart',
41
+ )
42
+
43
+ options = {
44
+ 'job': _complete_restart_jobs,
45
+ 'jobs': _complete_restart_jobs,
46
+ }
47
+
48
+ if (
49
+ len(action) > 0 and action[0] in options
50
+ and kw.get('line', '').split(' ')[-1] != action[0]
51
+ ):
52
+ sub = action[0]
53
+ del action[0]
54
+ return options[sub](action=action, **kw)
55
+
56
+ from meerschaum._internal.shell import default_action_completer
57
+ return default_action_completer(action=(['restart'] + action), **kw)
58
+
59
+
60
+ def _restart_jobs(
61
+ action: Optional[List[str]] = None,
62
+ executor_keys: Optional[str] = None,
63
+ loop: bool = False,
64
+ min_seconds: Optional[float] = 1.0,
65
+ debug: bool = False,
66
+ **kwargs: Any
67
+ ) -> SuccessTuple:
68
+ """
69
+ Restart stopped jobs which have not been manually stopped.
70
+ """
71
+ import time
72
+ from meerschaum.jobs import (
73
+ get_restart_jobs,
74
+ get_filtered_jobs,
75
+ check_restart_jobs,
76
+ )
77
+ from meerschaum.utils.misc import items_str
78
+ from meerschaum.utils.warnings import info
79
+ action = action or []
80
+
81
+ while True:
82
+ jobs = get_filtered_jobs(executor_keys, action, include_hidden=True, debug=debug)
83
+ restart_jobs = get_restart_jobs(executor_keys, jobs, debug=debug) if not action else jobs
84
+ if not restart_jobs and not loop:
85
+ return True, "No jobs need to be restarted."
86
+
87
+ info(
88
+ "Checking job"
89
+ + ('s' if len(restart_jobs) != 1 else '')
90
+ + ' '
91
+ + items_str(list(restart_jobs.keys()))
92
+ + '...'
93
+ )
94
+
95
+ check_success, check_msg = check_restart_jobs(
96
+ executor_keys,
97
+ restart_jobs,
98
+ debug=debug,
99
+ )
100
+ if not loop:
101
+ break
102
+
103
+ if min_seconds is not None and min_seconds != 0.0:
104
+ info(f"Sleeping for {min_seconds} seconds...")
105
+ time.sleep(min_seconds)
106
+
107
+ return check_success, check_msg