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
@@ -8,60 +8,162 @@ The entry point for launching Meerschaum actions.
8
8
  """
9
9
 
10
10
  from __future__ import annotations
11
- from meerschaum.utils.typing import SuccessTuple, List, Optional, Dict
12
11
 
13
- def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
14
- """Parse arguments and launch a Meerschaum action.
15
- The `action` list removes the first element.
16
-
17
- Examples of action:
18
- 'show actions' -> ['actions']
19
- 'show' -> []
12
+ import os
13
+ import sys
14
+ from meerschaum.utils.typing import SuccessTuple, List, Optional, Dict, Callable, Any
15
+ from meerschaum.config.static import STATIC_CONFIG as _STATIC_CONFIG
16
+
17
+ _systemd_result_path = None
18
+ if (_STATIC_CONFIG['environment']['systemd_log_path']) in os.environ:
19
+ from meerschaum.utils.daemon import RotatingFile as _RotatingFile, StdinFile as _StdinFile
20
+ from meerschaum.config import get_config as _get_config
21
+
22
+ _systemd_result_path = os.environ[_STATIC_CONFIG['environment']['systemd_result_path']]
23
+ _systemd_log_path = os.environ[_STATIC_CONFIG['environment']['systemd_log_path']]
24
+ _systemd_log = _RotatingFile(
25
+ _systemd_log_path,
26
+ write_timestamps=True,
27
+ timestamp_format=_get_config('jobs', 'logs', 'timestamps', 'format'),
28
+ )
29
+ sys.stdout = _systemd_log
30
+ sys.stderr = _systemd_log
31
+ _systemd_stdin_path = os.environ.get(_STATIC_CONFIG['environment']['systemd_stdin_path'], None)
32
+ if _systemd_stdin_path:
33
+ sys.stdin = _StdinFile(_systemd_stdin_path)
34
+
35
+ def entry(
36
+ sysargs: Optional[List[str]] = None,
37
+ _patch_args: Optional[Dict[str, Any]] = None,
38
+ ) -> SuccessTuple:
39
+ """
40
+ Parse arguments and launch a Meerschaum action.
20
41
 
21
42
  Returns
22
43
  -------
23
- A `SuccessTuple` indicating success. If `schedule` is provided, this will never return.
24
-
44
+ A `SuccessTuple` indicating success.
25
45
  """
26
- from meerschaum._internal.arguments import parse_arguments
46
+ import shlex
47
+ import json
48
+ from meerschaum.utils.formatting import make_header
49
+ from meerschaum._internal.arguments import (
50
+ parse_arguments,
51
+ split_chained_sysargs,
52
+ split_pipeline_sysargs,
53
+ )
27
54
  from meerschaum.config.static import STATIC_CONFIG
28
55
  if sysargs is None:
29
56
  sysargs = []
30
57
  if not isinstance(sysargs, list):
31
- import shlex
32
58
  sysargs = shlex.split(sysargs)
33
- args = parse_arguments(sysargs)
34
- argparse_exception = args.get(
35
- STATIC_CONFIG['system']['arguments']['failure_key'],
36
- None,
59
+
60
+ pipeline_key = STATIC_CONFIG['system']['arguments']['pipeline_key']
61
+ escaped_pipeline_key = STATIC_CONFIG['system']['arguments']['escaped_pipeline_key']
62
+ sysargs, pipeline_args = split_pipeline_sysargs(sysargs)
63
+
64
+ has_daemon = '-d' in sysargs or '--daemon' in sysargs
65
+ has_start_job = sysargs[:2] == ['start', 'job']
66
+ chained_sysargs = (
67
+ [sysargs]
68
+ if has_daemon or has_start_job
69
+ else split_chained_sysargs(sysargs)
37
70
  )
38
- if argparse_exception is not None:
39
- args_text = args.get('text', '')
40
- if not args_text.startswith('show arguments'):
41
- return (
42
- False,
71
+ if pipeline_args:
72
+ chained_sysargs = [
73
+ ['start', 'pipeline']
74
+ + [str(arg) for arg in pipeline_args]
75
+ + (
76
+ ['--params', json.dumps(_patch_args)]
77
+ if _patch_args
78
+ else []
79
+ )
80
+ + ['--sub-args', shlex.join(sysargs)]
81
+ ]
82
+
83
+ results: List[SuccessTuple] = []
84
+
85
+ for _sysargs in chained_sysargs:
86
+ if escaped_pipeline_key in _sysargs:
87
+ _sysargs = [
88
+ pipeline_key
89
+ if _arg == escaped_pipeline_key
90
+ else _arg
91
+ for _arg in _sysargs
92
+ ]
93
+
94
+ args = parse_arguments(_sysargs)
95
+ if _patch_args:
96
+ args.update(_patch_args)
97
+ argparse_exception = args.get(
98
+ STATIC_CONFIG['system']['arguments']['failure_key'],
99
+ None,
100
+ )
101
+ if argparse_exception is not None:
102
+ args_text = args.get('text', '')
103
+ if not args_text.startswith('show arguments'):
104
+ return (
105
+ False,
106
+ (
107
+ "Invalid arguments:"
108
+ + (f"\n{args_text}" if args_text else '')
109
+ + f"\n {argparse_exception}"
110
+ )
111
+ )
112
+
113
+ entry_success, entry_msg = entry_with_args(_patch_args=_patch_args, **args)
114
+ if not entry_success:
115
+ return entry_success, entry_msg
116
+
117
+ results.append((entry_success, entry_msg))
118
+
119
+ success = all(_success for _success, _ in results)
120
+ msg = (
121
+ results[0][1]
122
+ if len(results) == 1
123
+ else 'Successfully completed steps:\n\n' + '\n'.join(
124
+ [
43
125
  (
44
- "Invalid arguments:"
45
- + (f"\n{args_text}" if args_text else '')
46
- + f"\n {argparse_exception}"
126
+ make_header(shlex.join(_sysargs))
127
+ + '\n ' + _msg + '\n'
47
128
  )
48
- )
129
+ for i, ((_, _msg), _sysargs) in enumerate(zip(results, chained_sysargs))
130
+ ]
131
+ )
132
+ )
133
+ if _systemd_result_path:
134
+ import json
135
+ with open(_systemd_result_path, 'w+', encoding='utf-8') as f:
136
+ json.dump((success, msg), f)
49
137
 
50
- return entry_with_args(**args)
138
+ return success, msg
51
139
 
52
140
 
53
141
  def entry_with_args(
54
- _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
55
- **kw
56
- ) -> SuccessTuple:
142
+ _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
143
+ _patch_args: Optional[Dict[str, Any]] = None,
144
+ **kw
145
+ ) -> SuccessTuple:
57
146
  """Execute a Meerschaum action with keyword arguments.
58
147
  Use `_entry()` for parsing sysargs before executing.
59
148
  """
60
149
  import sys
61
150
  import functools
151
+ import inspect
62
152
  from meerschaum.actions import get_action, get_main_action_name
63
153
  from meerschaum._internal.arguments import remove_leading_action
64
- from meerschaum.utils.venv import Venv, active_venvs, deactivate_venv
154
+ from meerschaum.utils.venv import active_venvs, deactivate_venv
155
+ from meerschaum.config.static import STATIC_CONFIG
156
+
157
+ if _patch_args:
158
+ kw.update(_patch_args)
159
+
160
+ and_key = STATIC_CONFIG['system']['arguments']['and_key']
161
+ escaped_and_key = STATIC_CONFIG['system']['arguments']['escaped_and_key']
162
+ if and_key in (sysargs := kw.get('sysargs', [])):
163
+ if '-d' in sysargs or '--daemon' in sysargs:
164
+ sysargs = [(arg if arg != and_key else escaped_and_key) for arg in sysargs]
165
+ return entry(sysargs, _patch_args=_patch_args)
166
+
65
167
  if kw.get('trace', None):
66
168
  from meerschaum.utils.misc import debug_trace
67
169
  debug_trace()
@@ -72,6 +174,29 @@ def entry_with_args(
72
174
  ):
73
175
  return get_shell().cmdloop()
74
176
 
177
+ skip_schedule = False
178
+
179
+ executor_keys = kw.get('executor_keys', None)
180
+ if executor_keys is None:
181
+ executor_keys = 'local'
182
+
183
+ if executor_keys.startswith('api:'):
184
+ intended_action_function = get_action(kw['action'], _actions=_actions)
185
+ function_accepts_executor_keys = (
186
+ 'executor_keys' in inspect.signature(intended_action_function).parameters
187
+ if intended_action_function is not None
188
+ else False
189
+ )
190
+ if not function_accepts_executor_keys:
191
+ api_label = executor_keys.split(':')[-1]
192
+ kw['action'].insert(0, 'api')
193
+ kw['action'].insert(1, api_label)
194
+ skip_schedule = True
195
+
196
+ ### If the `--daemon` flag is present, prepend 'start job'.
197
+ if kw.get('daemon', False) and kw['action'][0] != 'stack':
198
+ kw['action'] = ['start', 'jobs'] + kw['action']
199
+
75
200
  action_function = get_action(kw['action'], _actions=_actions)
76
201
 
77
202
  ### If action does not exist, execute in a subshell.
@@ -86,7 +211,6 @@ def entry_with_args(
86
211
  ) else None
87
212
  )
88
213
 
89
- skip_schedule = False
90
214
  if (
91
215
  kw['action']
92
216
  and kw['action'][0] == 'start'
@@ -96,7 +220,13 @@ def entry_with_args(
96
220
 
97
221
  kw['action'] = remove_leading_action(kw['action'], _actions=_actions)
98
222
 
99
- do_action = functools.partial(_do_action_wrapper, action_function, plugin_name, **kw)
223
+ do_action = functools.partial(
224
+ _do_action_wrapper,
225
+ action_function,
226
+ plugin_name,
227
+ **kw
228
+ )
229
+
100
230
  if kw.get('schedule', None) and not skip_schedule:
101
231
  from meerschaum.utils.schedule import schedule_function
102
232
  from meerschaum.utils.misc import interval_str
@@ -139,16 +269,16 @@ def _do_action_wrapper(action_function, plugin_name, **kw):
139
269
  )
140
270
  )
141
271
  except KeyboardInterrupt:
142
- result = False, f"Cancelled action `{action_name}`."
272
+ result = False, f"Cancelled action `{action_name.lstrip()}`."
143
273
  return result
144
274
 
145
275
  _shells = []
146
276
  _shell = None
147
277
  def get_shell(
148
- sysargs: Optional[List[str]] = None,
149
- reload: bool = False,
150
- debug: bool = False
151
- ):
278
+ sysargs: Optional[List[str]] = None,
279
+ reload: bool = False,
280
+ debug: bool = False
281
+ ):
152
282
  """Initialize and return the Meerschaum shell object."""
153
283
  global _shell
154
284
  from meerschaum.utils.debug import dprint