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.
- meerschaum/__init__.py +6 -1
- meerschaum/__main__.py +0 -5
- meerschaum/_internal/arguments/__init__.py +1 -1
- meerschaum/_internal/arguments/_parse_arguments.py +72 -6
- meerschaum/_internal/arguments/_parser.py +45 -15
- meerschaum/_internal/docs/index.py +265 -8
- meerschaum/_internal/entry.py +154 -24
- meerschaum/_internal/shell/Shell.py +264 -77
- meerschaum/actions/__init__.py +29 -17
- meerschaum/actions/api.py +12 -12
- meerschaum/actions/attach.py +113 -0
- meerschaum/actions/copy.py +68 -41
- meerschaum/actions/delete.py +112 -50
- meerschaum/actions/edit.py +3 -3
- meerschaum/actions/install.py +40 -32
- meerschaum/actions/pause.py +44 -27
- meerschaum/actions/restart.py +107 -0
- meerschaum/actions/show.py +130 -159
- meerschaum/actions/start.py +161 -100
- meerschaum/actions/stop.py +78 -42
- meerschaum/api/_events.py +25 -1
- meerschaum/api/_oauth2.py +2 -0
- meerschaum/api/_websockets.py +2 -2
- meerschaum/api/dash/callbacks/jobs.py +36 -44
- meerschaum/api/dash/jobs.py +89 -78
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +148 -17
- meerschaum/api/routes/_jobs.py +407 -0
- meerschaum/api/routes/_pipes.py +5 -5
- meerschaum/config/_default.py +1 -0
- meerschaum/config/_jobs.py +1 -1
- meerschaum/config/_paths.py +7 -0
- meerschaum/config/_shell.py +8 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +17 -0
- meerschaum/connectors/Connector.py +13 -7
- meerschaum/connectors/__init__.py +28 -15
- meerschaum/connectors/api/APIConnector.py +27 -1
- meerschaum/connectors/api/_actions.py +71 -6
- meerschaum/connectors/api/_jobs.py +368 -0
- meerschaum/connectors/api/_pipes.py +85 -84
- meerschaum/connectors/parse.py +27 -15
- meerschaum/core/Pipe/_bootstrap.py +16 -8
- meerschaum/jobs/_Executor.py +69 -0
- meerschaum/jobs/_Job.py +899 -0
- meerschaum/jobs/__init__.py +396 -0
- meerschaum/jobs/systemd.py +694 -0
- meerschaum/plugins/__init__.py +97 -12
- meerschaum/utils/daemon/Daemon.py +276 -30
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +5 -5
- meerschaum/utils/daemon/RotatingFile.py +14 -7
- meerschaum/utils/daemon/StdinFile.py +121 -0
- meerschaum/utils/daemon/__init__.py +15 -7
- meerschaum/utils/daemon/_names.py +15 -13
- meerschaum/utils/formatting/__init__.py +2 -1
- meerschaum/utils/formatting/_jobs.py +115 -62
- meerschaum/utils/formatting/_shell.py +6 -0
- meerschaum/utils/misc.py +41 -22
- meerschaum/utils/packages/_packages.py +9 -6
- meerschaum/utils/process.py +9 -9
- meerschaum/utils/prompt.py +16 -8
- meerschaum/utils/venv/__init__.py +2 -2
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/METADATA +22 -25
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/RECORD +70 -61
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/WHEEL +1 -1
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/LICENSE +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/NOTICE +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dist-info}/zip-safe +0 -0
meerschaum/__init__.py
CHANGED
@@ -20,15 +20,17 @@ limitations under the License.
|
|
20
20
|
|
21
21
|
import atexit
|
22
22
|
from meerschaum.utils.typing import SuccessTuple
|
23
|
+
from meerschaum.utils.packages import attempt_import
|
23
24
|
from meerschaum.core.Pipe import Pipe
|
24
25
|
from meerschaum.plugins import Plugin
|
25
26
|
from meerschaum.utils.venv import Venv
|
27
|
+
from meerschaum.jobs import Job, make_executor
|
26
28
|
from meerschaum.connectors import get_connector, Connector, make_connector
|
27
29
|
from meerschaum.utils import get_pipes
|
28
30
|
from meerschaum.utils.formatting import pprint
|
29
31
|
from meerschaum._internal.docs import index as __doc__
|
30
32
|
from meerschaum.config import __version__, get_config
|
31
|
-
from meerschaum.
|
33
|
+
from meerschaum._internal.entry import entry
|
32
34
|
from meerschaum.__main__ import _close_pools
|
33
35
|
|
34
36
|
atexit.register(_close_pools)
|
@@ -42,14 +44,17 @@ __all__ = (
|
|
42
44
|
"Plugin",
|
43
45
|
"Venv",
|
44
46
|
"Plugin",
|
47
|
+
"Job",
|
45
48
|
"pprint",
|
46
49
|
"attempt_import",
|
47
50
|
"actions",
|
48
51
|
"config",
|
49
52
|
"connectors",
|
53
|
+
"jobs",
|
50
54
|
"plugins",
|
51
55
|
"utils",
|
52
56
|
"SuccessTuple",
|
53
57
|
"Connector",
|
54
58
|
"make_connector",
|
59
|
+
"entry",
|
55
60
|
)
|
meerschaum/__main__.py
CHANGED
@@ -45,11 +45,6 @@ def main(sysargs: Optional[List[str]] = None) -> None:
|
|
45
45
|
parse_version(sysargs)
|
46
46
|
return _exit(old_cwd=old_cwd)
|
47
47
|
|
48
|
-
if ('-d' in sysargs or '--daemon' in sysargs) and ('stack' not in sysargs):
|
49
|
-
from meerschaum.utils.daemon import daemon_entry
|
50
|
-
_print_tuple(daemon_entry(sysargs), upper_padding=1)
|
51
|
-
return _exit(old_cwd=old_cwd)
|
52
|
-
|
53
48
|
from meerschaum._internal.entry import entry, get_shell
|
54
49
|
|
55
50
|
### Try to launch a shell if --shell is provided.
|
@@ -8,7 +8,7 @@ This package includes argument parsing utilities.
|
|
8
8
|
|
9
9
|
from meerschaum._internal.arguments._parse_arguments import (
|
10
10
|
parse_arguments, parse_line, remove_leading_action,
|
11
|
-
parse_dict_to_sysargs,
|
11
|
+
parse_dict_to_sysargs, split_chained_sysargs, split_pipeline_sysargs,
|
12
12
|
)
|
13
13
|
from meerschaum._internal.arguments._parser import parser
|
14
14
|
from meerschaum.plugins import add_plugin_argument
|
@@ -10,7 +10,7 @@ This module contains functions for parsing arguments
|
|
10
10
|
from __future__ import annotations
|
11
11
|
import json
|
12
12
|
from datetime import timedelta
|
13
|
-
from meerschaum.utils.typing import List, Dict, Any, Optional, Callable, SuccessTuple
|
13
|
+
from meerschaum.utils.typing import List, Dict, Any, Optional, Callable, SuccessTuple, Tuple
|
14
14
|
from meerschaum.utils.threading import RLock
|
15
15
|
|
16
16
|
_locks = {
|
@@ -18,6 +18,59 @@ _locks = {
|
|
18
18
|
}
|
19
19
|
_loaded_plugins_args: bool = False
|
20
20
|
|
21
|
+
def split_pipeline_sysargs(sysargs: List[str]) -> Tuple[List[str], List[str]]:
|
22
|
+
"""
|
23
|
+
Split `sysargs` into the main pipeline and the flags following the pipeline separator (`:`).
|
24
|
+
"""
|
25
|
+
from meerschaum.config.static import STATIC_CONFIG
|
26
|
+
pipeline_key = STATIC_CONFIG['system']['arguments']['pipeline_key']
|
27
|
+
if pipeline_key not in sysargs:
|
28
|
+
return sysargs, []
|
29
|
+
|
30
|
+
### Find the index of the last occurrence of `:`.
|
31
|
+
pipeline_ix = len(sysargs) - 1 - sysargs[::-1].index(pipeline_key)
|
32
|
+
sysargs_after_pipeline_key = sysargs[pipeline_ix+1:]
|
33
|
+
sysargs = [arg for arg in sysargs[:pipeline_ix] if arg != pipeline_key]
|
34
|
+
return sysargs, sysargs_after_pipeline_key
|
35
|
+
|
36
|
+
|
37
|
+
def split_chained_sysargs(sysargs: List[str]) -> List[List[str]]:
|
38
|
+
"""
|
39
|
+
Split a `sysargs` list containing "and" keys (`+`)
|
40
|
+
into a list of individual `sysargs`.
|
41
|
+
"""
|
42
|
+
from meerschaum.config.static import STATIC_CONFIG
|
43
|
+
and_key = STATIC_CONFIG['system']['arguments']['and_key']
|
44
|
+
|
45
|
+
if not sysargs or and_key not in sysargs:
|
46
|
+
return [sysargs]
|
47
|
+
|
48
|
+
### Coalesce and consecutive joiners into one.
|
49
|
+
coalesce_args = []
|
50
|
+
previous_arg = None
|
51
|
+
for arg in [_arg for _arg in sysargs]:
|
52
|
+
if arg == and_key and previous_arg == and_key:
|
53
|
+
continue
|
54
|
+
coalesce_args.append(arg)
|
55
|
+
previous_arg = arg
|
56
|
+
|
57
|
+
### Remove any joiners from the ends.
|
58
|
+
if coalesce_args[0] == and_key:
|
59
|
+
coalesce_args = coalesce_args[1:]
|
60
|
+
if coalesce_args[-1] == and_key:
|
61
|
+
coalesce_args = coalesce_args[:-1]
|
62
|
+
|
63
|
+
chained_sysargs = []
|
64
|
+
current_sysargs = []
|
65
|
+
for arg in coalesce_args:
|
66
|
+
if arg != and_key:
|
67
|
+
current_sysargs.append(arg)
|
68
|
+
else:
|
69
|
+
chained_sysargs.append(current_sysargs)
|
70
|
+
current_sysargs = []
|
71
|
+
chained_sysargs.append(current_sysargs)
|
72
|
+
return chained_sysargs
|
73
|
+
|
21
74
|
|
22
75
|
def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
|
23
76
|
"""
|
@@ -206,9 +259,14 @@ def parse_dict_to_sysargs(
|
|
206
259
|
args_dict: Dict[str, Any]
|
207
260
|
) -> List[str]:
|
208
261
|
"""Revert an arguments dictionary back to a command line list."""
|
262
|
+
import shlex
|
209
263
|
from meerschaum._internal.arguments._parser import get_arguments_triggers
|
210
|
-
|
211
|
-
|
264
|
+
from meerschaum.config.static import STATIC_CONFIG
|
265
|
+
from meerschaum.utils.warnings import warn
|
266
|
+
|
267
|
+
action = args_dict.get('action', None)
|
268
|
+
sysargs: List[str] = []
|
269
|
+
sysargs.extend(action or [])
|
212
270
|
allow_none_args = {'location_keys'}
|
213
271
|
|
214
272
|
triggers = get_arguments_triggers()
|
@@ -216,6 +274,7 @@ def parse_dict_to_sysargs(
|
|
216
274
|
for a, t in triggers.items():
|
217
275
|
if a == 'action' or a not in args_dict:
|
218
276
|
continue
|
277
|
+
|
219
278
|
### Add boolean flags
|
220
279
|
if isinstance(args_dict[a], bool):
|
221
280
|
if args_dict[a] is True:
|
@@ -288,9 +347,6 @@ def remove_leading_action(
|
|
288
347
|
for a in action:
|
289
348
|
_action.append(a.replace('_', UNDERSCORE_STANDIN))
|
290
349
|
|
291
|
-
### e.g. 'show_pipes_baz'
|
292
|
-
action_str = '_'.join(_action)
|
293
|
-
|
294
350
|
### e.g. 'show_pipes'
|
295
351
|
action_name = action_function.__name__.lstrip('_')
|
296
352
|
|
@@ -300,6 +356,16 @@ def remove_leading_action(
|
|
300
356
|
### Strip away any leading prefices.
|
301
357
|
action_name = action_name[main_action_index:]
|
302
358
|
|
359
|
+
subaction_parts = action_name.replace(main_action_name, '').lstrip('_').split('_')
|
360
|
+
subaction_name = subaction_parts[0] if subaction_parts else None
|
361
|
+
|
362
|
+
### e.g. 'pipe' -> 'pipes'
|
363
|
+
if subaction_name and subaction_name.endswith('s') and not action[1].endswith('s'):
|
364
|
+
_action[1] += 's'
|
365
|
+
|
366
|
+
### e.g. 'show_pipes_baz'
|
367
|
+
action_str = '_'.join(_action)
|
368
|
+
|
303
369
|
if not action_str.replace(UNDERSCORE_STANDIN, '_').startswith(action_name):
|
304
370
|
warn(f"Unable to parse '{action_str}' for action '{action_name}'.")
|
305
371
|
return action
|
@@ -62,7 +62,24 @@ def parse_datetime(dt_str: str) -> Union[datetime, int, str]:
|
|
62
62
|
return dt
|
63
63
|
|
64
64
|
|
65
|
-
def
|
65
|
+
def parse_executor_keys(executor_keys_str: str) -> Union[str, None]:
|
66
|
+
"""
|
67
|
+
Ensure that only API keys are provided for executor_keys.
|
68
|
+
"""
|
69
|
+
if executor_keys_str in ('local', 'systemd'):
|
70
|
+
return executor_keys_str
|
71
|
+
|
72
|
+
if executor_keys_str.lower() == 'none':
|
73
|
+
return 'local'
|
74
|
+
|
75
|
+
if not executor_keys_str.startswith('api:'):
|
76
|
+
from meerschaum.utils.warnings import error
|
77
|
+
error(f"Invalid exectutor keys '{executor_keys_str}'.", stack=False)
|
78
|
+
|
79
|
+
return executor_keys_str
|
80
|
+
|
81
|
+
|
82
|
+
def parse_help(sysargs: Union[List[str], Dict[str, Any]]) -> None:
|
66
83
|
"""Parse the `--help` flag to determine which help message to print."""
|
67
84
|
from meerschaum._internal.arguments._parse_arguments import parse_arguments, parse_line
|
68
85
|
from meerschaum.actions import actions, get_subactions
|
@@ -135,6 +152,7 @@ _seen_plugin_args = {}
|
|
135
152
|
|
136
153
|
groups = {}
|
137
154
|
groups['actions'] = parser.add_argument_group(title='Actions options')
|
155
|
+
groups['jobs'] = parser.add_argument_group(title='Jobs options')
|
138
156
|
groups['pipes'] = parser.add_argument_group(title='Pipes options')
|
139
157
|
groups['sync'] = parser.add_argument_group(title='Sync options')
|
140
158
|
groups['api'] = parser.add_argument_group(title='API options')
|
@@ -166,18 +184,25 @@ groups['actions'].add_argument(
|
|
166
184
|
help="Automatically choose the defaults answers to questions. Does not result in data loss.",
|
167
185
|
)
|
168
186
|
groups['actions'].add_argument(
|
169
|
-
'-
|
170
|
-
help =
|
187
|
+
'-A', '--sub-args', nargs=argparse.REMAINDER,
|
188
|
+
help = (
|
189
|
+
"Provide a list of arguments for subprocesses. " +
|
190
|
+
"You can also type sub-arguments in [] instead." +
|
191
|
+
" E.g. `stack -A='--version'`, `ls [-lh]`, `echo -A these are sub-arguments`"
|
192
|
+
)
|
171
193
|
)
|
172
|
-
|
173
|
-
|
194
|
+
|
195
|
+
### Jobs options
|
196
|
+
groups['jobs'].add_argument(
|
197
|
+
'-d', '--daemon', action='store_true',
|
198
|
+
help = "Run an action as a background daemon to create a job."
|
174
199
|
)
|
175
|
-
groups['
|
200
|
+
groups['jobs'].add_argument(
|
176
201
|
'--name', '--job-name', type=parse_name, help=(
|
177
202
|
"Assign a name to a job. If no name is provided, a random name will be assigned."
|
178
203
|
),
|
179
204
|
)
|
180
|
-
groups['
|
205
|
+
groups['jobs'].add_argument(
|
181
206
|
'-s', '--schedule', '--cron', type=str,
|
182
207
|
help = (
|
183
208
|
"Continue executing the action according to a schedule (e.g. 'every 1 seconds'). \n"
|
@@ -185,15 +210,20 @@ groups['actions'].add_argument(
|
|
185
210
|
+ "https://red-engine.readthedocs.io/en/stable/condition_syntax/index.html"
|
186
211
|
)
|
187
212
|
)
|
188
|
-
groups['
|
189
|
-
'
|
190
|
-
help
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
213
|
+
groups['jobs'].add_argument(
|
214
|
+
'--restart', action='store_true',
|
215
|
+
help=("Restart a job if not stopped manually."),
|
216
|
+
)
|
217
|
+
groups['jobs'].add_argument(
|
218
|
+
'-e', '--executor-keys', type=parse_executor_keys,
|
219
|
+
help=(
|
220
|
+
"Execute jobs locally or remotely. "
|
221
|
+
"Supported values are 'local', 'systemd', and 'api:{label}'."
|
222
|
+
),
|
223
|
+
)
|
224
|
+
groups['jobs'].add_argument(
|
225
|
+
'--rm', action='store_true', help="Delete a job once it has finished executing."
|
195
226
|
)
|
196
|
-
|
197
227
|
### Pipes options
|
198
228
|
groups['pipes'].add_argument(
|
199
229
|
'-c', '-C', '--connector-keys', nargs='+',
|
@@ -36,8 +36,9 @@ For your convenience, the following classes and functions may be imported from t
|
|
36
36
|
<li><code>meerschaum.Connector</code></li>
|
37
37
|
<li><code>meerschaum.Pipe</code></li>
|
38
38
|
<li><code>meerschaum.Plugin</code></li>
|
39
|
-
<li><code>meerschaum.
|
39
|
+
<li><code>meerschaum.Job</code></li>
|
40
40
|
<li><code>meerschaum.Venv</code></li>
|
41
|
+
<li><code>meerschaum.SuccessTuple</code></li>
|
41
42
|
</ul>
|
42
43
|
|
43
44
|
</div>
|
@@ -54,6 +55,7 @@ For your convenience, the following classes and functions may be imported from t
|
|
54
55
|
<li><code>meerschaum.make_connector()</code></li>
|
55
56
|
<li><code>meerschaum.pprint()</code></li>
|
56
57
|
<li><code>meerschaum.attempt_import()</code></li>
|
58
|
+
<li><code>meerschaum.entry()</code></li>
|
57
59
|
</ul>
|
58
60
|
|
59
61
|
</div>
|
@@ -61,7 +63,10 @@ For your convenience, the following classes and functions may be imported from t
|
|
61
63
|
|
62
64
|
### Examples
|
63
65
|
|
64
|
-
|
66
|
+
<details>
|
67
|
+
<summary><b>Build a Connector</b></summary>
|
68
|
+
|
69
|
+
Get existing connectors or build a new one in-memory with the `meerschaum.get_connector()` factory function:
|
65
70
|
|
66
71
|
```python
|
67
72
|
import meerschaum as mrsm
|
@@ -80,9 +85,14 @@ sql_conn.to_sql(df, 'foo')
|
|
80
85
|
print(sql_conn.read('foo'))
|
81
86
|
# foo
|
82
87
|
# 0 1
|
88
|
+
|
83
89
|
```
|
90
|
+
</details>
|
91
|
+
|
92
|
+
<details>
|
93
|
+
<summary><b>Create a Custom Connector Class</b></summary>
|
84
94
|
|
85
|
-
|
95
|
+
Decorate your connector classes with `meerschaum.make_connector()` to designate it as a custom connector:
|
86
96
|
|
87
97
|
```python
|
88
98
|
from datetime import datetime, timezone
|
@@ -113,8 +123,12 @@ foo_conn = mrsm.get_connector(
|
|
113
123
|
)
|
114
124
|
docs = foo_conn.fetch()
|
115
125
|
```
|
126
|
+
</details>
|
116
127
|
|
117
|
-
|
128
|
+
<details>
|
129
|
+
<summary><b>Build a Pipe</b></summary>
|
130
|
+
|
131
|
+
Build a `meerschaum.Pipe` in-memory:
|
118
132
|
|
119
133
|
```python
|
120
134
|
from datetime import datetime
|
@@ -135,7 +149,23 @@ print(df)
|
|
135
149
|
# 2 2024-01-01 3 96
|
136
150
|
```
|
137
151
|
|
138
|
-
|
152
|
+
Add `temporary=True` to skip registering the pipe in the pipes table.
|
153
|
+
|
154
|
+
</details>
|
155
|
+
|
156
|
+
<details>
|
157
|
+
<summary><b>Get Registered Pipes</b></summary>
|
158
|
+
|
159
|
+
The `meerschaum.get_pipes()` function returns a dictionary hierarchy of pipes by connector, metric, and location:
|
160
|
+
|
161
|
+
```python
|
162
|
+
import meerschaum as mrsm
|
163
|
+
|
164
|
+
pipes = mrsm.get_pipes(instance='sql:temp')
|
165
|
+
pipe = pipes['foo:bar']['demo'][None]
|
166
|
+
```
|
167
|
+
|
168
|
+
Add `as_list=True` to flatten the hierarchy:
|
139
169
|
|
140
170
|
```python
|
141
171
|
import meerschaum as mrsm
|
@@ -148,8 +178,12 @@ pipes = mrsm.get_pipes(
|
|
148
178
|
print(pipes)
|
149
179
|
# [Pipe('foo:bar', 'demo', instance='sql:temp')]
|
150
180
|
```
|
181
|
+
</details>
|
151
182
|
|
152
|
-
|
183
|
+
<details>
|
184
|
+
<summary><b>Import Plugins</b></summary>
|
185
|
+
|
186
|
+
You can import a plugin's module through `meerschaum.Plugin.module`:
|
153
187
|
|
154
188
|
```python
|
155
189
|
import meerschaum as mrsm
|
@@ -157,10 +191,211 @@ import meerschaum as mrsm
|
|
157
191
|
plugin = mrsm.Plugin('noaa')
|
158
192
|
with mrsm.Venv(plugin):
|
159
193
|
noaa = plugin.module
|
160
|
-
print(noaa.get_station_info('KGMU'))
|
161
|
-
# {'name': 'Greenville Downtown Airport', 'geometry': {'type': 'Point', 'coordinates': [-82.35004, 34.84873]}}
|
162
194
|
```
|
163
195
|
|
196
|
+
If your plugin has submodules, use `meerschaum.plugins.from_plugin_import`:
|
197
|
+
|
198
|
+
```python
|
199
|
+
from meerschaum.plugins import from_plugin_import
|
200
|
+
get_defined_pipes = from_plugin_import('compose.utils.pipes', 'get_defined_pipes')
|
201
|
+
```
|
202
|
+
|
203
|
+
Import multiple plugins with `meerschaum.plugins.import_plugins`:
|
204
|
+
|
205
|
+
```python
|
206
|
+
from meerschaum.plugins import import_plugins
|
207
|
+
noaa, compose = import_plugins('noaa', 'compose')
|
208
|
+
```
|
209
|
+
|
210
|
+
</details>
|
211
|
+
|
212
|
+
<details>
|
213
|
+
<summary><b>Create a Job</b></summary>
|
214
|
+
|
215
|
+
Create a `meerschaum.Job` with `name` and `sysargs`:
|
216
|
+
|
217
|
+
```python
|
218
|
+
import meerschaum as mrsm
|
219
|
+
|
220
|
+
job = mrsm.Job('syncing-engine', 'sync pipes --loop')
|
221
|
+
success, msg = job.start()
|
222
|
+
```
|
223
|
+
|
224
|
+
Pass `executor_keys` as the connectors keys of an API instance to create a remote job:
|
225
|
+
|
226
|
+
```python
|
227
|
+
import meerschaum as mrsm
|
228
|
+
|
229
|
+
job = mrsm.Job(
|
230
|
+
'foo',
|
231
|
+
'sync pipes -s daily',
|
232
|
+
executor_keys='api:main',
|
233
|
+
)
|
234
|
+
```
|
235
|
+
|
236
|
+
</details>
|
237
|
+
|
238
|
+
<details>
|
239
|
+
<summary><b>Import from a Virtual Environment</b></summary>
|
240
|
+
Use the `meerschaum.Venv` context manager to activate a virtual environment:
|
241
|
+
```python
|
242
|
+
import meerschaum as mrsm
|
243
|
+
|
244
|
+
with mrsm.Venv('noaa'):
|
245
|
+
import requests
|
246
|
+
|
247
|
+
print(requests.__file__)
|
248
|
+
# /home/bmeares/.config/meerschaum/venvs/noaa/lib/python3.12/site-packages/requests/__init__.py
|
249
|
+
```
|
250
|
+
|
251
|
+
To import packages which may not be installed, use `meerschaum.attempt_import()`:
|
252
|
+
|
253
|
+
```python
|
254
|
+
import meerschaum as mrsm
|
255
|
+
|
256
|
+
requests = mrsm.attempt_import('requests', venv='noaa')
|
257
|
+
print(requests.__file__)
|
258
|
+
# /home/bmeares/.config/meerschaum/venvs/noaa/lib/python3.12/site-packages/requests/__init__.py
|
259
|
+
```
|
260
|
+
|
261
|
+
</details>
|
262
|
+
|
263
|
+
<details>
|
264
|
+
<summary><b>Run Actions</b></summary>
|
265
|
+
|
266
|
+
Run `sysargs` with `meerschaum.entry()`:
|
267
|
+
|
268
|
+
```python
|
269
|
+
import meerschaum as mrsm
|
270
|
+
|
271
|
+
success, msg = mrsm.entry('show pipes + show version : x2')
|
272
|
+
```
|
273
|
+
|
274
|
+
Use `meerschaum.actions.get_action()` to access an action function directly:
|
275
|
+
|
276
|
+
```python
|
277
|
+
from meerschaum.actions import get_action
|
278
|
+
|
279
|
+
show_pipes = get_action(['show', 'pipes'])
|
280
|
+
success, msg = show_pipes(connector_keys=['plugin:noaa'])
|
281
|
+
```
|
282
|
+
|
283
|
+
Get a dictionary of available subactions with `meerschaum.actions.get_subactions()`:
|
284
|
+
|
285
|
+
```python
|
286
|
+
from meerschaum.actions import get_subactions
|
287
|
+
|
288
|
+
subactions = get_subactions('show')
|
289
|
+
success, msg = subactions['pipes']()
|
290
|
+
```
|
291
|
+
|
292
|
+
</details>
|
293
|
+
|
294
|
+
<details>
|
295
|
+
<summary><b>Create a Plugin</b></summary>
|
296
|
+
|
297
|
+
Run `bootstrap plugin` to create a new plugin:
|
298
|
+
|
299
|
+
```
|
300
|
+
mrsm bootstrap plugin example
|
301
|
+
```
|
302
|
+
|
303
|
+
This will create `example.py` in your plugins directory (default `~/.config/meerschaum/plugins/`, Windows: `%APPDATA%\Meerschaum\plugins`). You may paste the example code from the "Create a Custom Action" example below.
|
304
|
+
|
305
|
+
Open your plugin with `edit plugin`:
|
306
|
+
|
307
|
+
```
|
308
|
+
mrsm edit plugin example
|
309
|
+
```
|
310
|
+
|
311
|
+
*Run `edit plugin` and paste the example code below to try out the features.*
|
312
|
+
|
313
|
+
See the [writing plugins guide](https://meerschaum.io/reference/plugins/writing-plugins/) for more in-depth documentation.
|
314
|
+
|
315
|
+
</details>
|
316
|
+
|
317
|
+
<details>
|
318
|
+
<summary><b>Create a Custom Action</b></summary>
|
319
|
+
|
320
|
+
Decorate a function with `meerschaum.actions.make_action` to designate it as an action. Subactions will be automatically detected if not decorated:
|
321
|
+
|
322
|
+
```python
|
323
|
+
from meerschaum.actions import make_action
|
324
|
+
|
325
|
+
@make_action
|
326
|
+
def sing():
|
327
|
+
print('What would you like me to sing?')
|
328
|
+
return True, "Success"
|
329
|
+
|
330
|
+
def sing_tune():
|
331
|
+
return False, "I don't know that song!"
|
332
|
+
|
333
|
+
def sing_song():
|
334
|
+
print('Hello, World!')
|
335
|
+
return True, "Success"
|
336
|
+
|
337
|
+
```
|
338
|
+
|
339
|
+
Use `meerschaum.plugins.add_plugin_argument()` to create new parameters for your action:
|
340
|
+
|
341
|
+
```python
|
342
|
+
from meerschaum.plugins import make_action, add_plugin_argument
|
343
|
+
|
344
|
+
add_plugin_argument(
|
345
|
+
'--song', type=str, help='What song to sing.',
|
346
|
+
)
|
347
|
+
|
348
|
+
@make_action
|
349
|
+
def sing_melody(action=None, song=None):
|
350
|
+
to_sing = action[0] if action else song
|
351
|
+
if not to_sing:
|
352
|
+
return False, "Please tell me what to sing!"
|
353
|
+
|
354
|
+
return True, f'~I am singing {to_sing}~'
|
355
|
+
```
|
356
|
+
|
357
|
+
```
|
358
|
+
mrsm sing melody lalala
|
359
|
+
|
360
|
+
mrsm sing melody --song do-re-mi
|
361
|
+
```
|
362
|
+
|
363
|
+
</details>
|
364
|
+
|
365
|
+
<details>
|
366
|
+
<summary><b>Add a Page to the Web Dashboard</b></summary>
|
367
|
+
Use the decorators `meerschaum.plugins.dash_plugin()` and `meerschaum.plugins.web_page()` to add new pages to the web dashboard:
|
368
|
+
|
369
|
+
```python
|
370
|
+
from meerschaum.plugins import dash_plugin, web_page
|
371
|
+
|
372
|
+
@dash_plugin
|
373
|
+
def init_dash(dash_app):
|
374
|
+
|
375
|
+
import dash.html as html
|
376
|
+
import dash_bootstrap_components as dbc
|
377
|
+
from dash import Input, Output, no_update
|
378
|
+
|
379
|
+
### Routes to '/dash/my-page'
|
380
|
+
@web_page('/my-page', login_required=False)
|
381
|
+
def my_page():
|
382
|
+
return dbc.Container([
|
383
|
+
html.H1("Hello, World!"),
|
384
|
+
dbc.Button("Click me", id='my-button'),
|
385
|
+
html.Div(id="my-output-div"),
|
386
|
+
])
|
387
|
+
|
388
|
+
@dash_app.callback(
|
389
|
+
Output('my-output-div', 'children'),
|
390
|
+
Input('my-button', 'n_clicks'),
|
391
|
+
)
|
392
|
+
def my_button_click(n_clicks):
|
393
|
+
if not n_clicks:
|
394
|
+
return no_update
|
395
|
+
return html.P(f'You clicked {n_clicks} times!')
|
396
|
+
```
|
397
|
+
</details>
|
398
|
+
|
164
399
|
## Submodules
|
165
400
|
|
166
401
|
<details>
|
@@ -206,6 +441,28 @@ with mrsm.Venv(plugin):
|
|
206
441
|
|
207
442
|
</details>
|
208
443
|
|
444
|
+
<details>
|
445
|
+
<summary>
|
446
|
+
`meerschaum.jobs`<br>
|
447
|
+
Start background jobs.
|
448
|
+
</summary>
|
449
|
+
|
450
|
+
- `meerschaum.jobs.Job`
|
451
|
+
- `meerschaum.jobs.Executor`
|
452
|
+
- `meerschaum.jobs.systemd.SystemdExecutor`
|
453
|
+
- `meerschaum.jobs.get_jobs()`
|
454
|
+
- `meerschaum.jobs.get_filtered_jobs()`
|
455
|
+
- `meerschaum.jobs.get_running_jobs()`
|
456
|
+
- `meerschaum.jobs.get_stopped_jobs()`
|
457
|
+
- `meerschaum.jobs.get_paused_jobs()`
|
458
|
+
- `meerschaum.jobs.get_restart_jobs()`
|
459
|
+
- `meerschaum.jobs.make_executor()`
|
460
|
+
- `meerschaum.jobs.check_restart_jobs()`
|
461
|
+
- `meerschaum.jobs.start_check_jobs_thread()`
|
462
|
+
- `meerschaum.jobs.stop_check_jobs_thread()`
|
463
|
+
|
464
|
+
</details>
|
465
|
+
|
209
466
|
<details>
|
210
467
|
<summary>
|
211
468
|
`meerschaum.plugins`<br>
|