meerschaum 2.3.0rc3__py3-none-any.whl → 2.3.1__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 +2 -3
- meerschaum/_internal/arguments/__init__.py +1 -1
- meerschaum/_internal/arguments/_parse_arguments.py +33 -22
- meerschaum/_internal/arguments/_parser.py +4 -7
- meerschaum/_internal/docs/index.py +265 -8
- meerschaum/_internal/entry.py +42 -4
- meerschaum/_internal/shell/Shell.py +84 -72
- meerschaum/actions/__init__.py +21 -11
- meerschaum/actions/show.py +5 -5
- meerschaum/actions/start.py +71 -1
- meerschaum/api/routes/_actions.py +48 -1
- meerschaum/config/_paths.py +1 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +2 -0
- meerschaum/connectors/__init__.py +1 -2
- meerschaum/connectors/api/APIConnector.py +6 -1
- meerschaum/connectors/api/_actions.py +77 -1
- meerschaum/connectors/api/_pipes.py +85 -84
- meerschaum/jobs/_Job.py +38 -6
- meerschaum/jobs/__init__.py +5 -3
- meerschaum/jobs/{_SystemdExecutor.py → systemd.py} +39 -22
- meerschaum/plugins/_Plugin.py +1 -1
- meerschaum/plugins/__init__.py +2 -1
- meerschaum/utils/daemon/StdinFile.py +1 -0
- meerschaum/utils/daemon/_names.py +14 -12
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/METADATA +1 -1
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/RECORD +33 -34
- meerschaum/jobs/_LocalExecutor.py +0 -88
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/WHEEL +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/zip-safe +0 -0
meerschaum/__init__.py
CHANGED
@@ -24,7 +24,7 @@ from meerschaum.utils.packages import attempt_import
|
|
24
24
|
from meerschaum.core.Pipe import Pipe
|
25
25
|
from meerschaum.plugins import Plugin
|
26
26
|
from meerschaum.utils.venv import Venv
|
27
|
-
from meerschaum.jobs import Job,
|
27
|
+
from meerschaum.jobs import Job, make_executor
|
28
28
|
from meerschaum.connectors import get_connector, Connector, make_connector
|
29
29
|
from meerschaum.utils import get_pipes
|
30
30
|
from meerschaum.utils.formatting import pprint
|
@@ -45,13 +45,12 @@ __all__ = (
|
|
45
45
|
"Venv",
|
46
46
|
"Plugin",
|
47
47
|
"Job",
|
48
|
-
"Executor",
|
49
|
-
"make_executor",
|
50
48
|
"pprint",
|
51
49
|
"attempt_import",
|
52
50
|
"actions",
|
53
51
|
"config",
|
54
52
|
"connectors",
|
53
|
+
"jobs",
|
55
54
|
"plugins",
|
56
55
|
"utils",
|
57
56
|
"SuccessTuple",
|
@@ -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, split_chained_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,10 +18,25 @@ _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
|
+
|
21
36
|
|
22
37
|
def split_chained_sysargs(sysargs: List[str]) -> List[List[str]]:
|
23
38
|
"""
|
24
|
-
Split a `sysargs` list containing "and" keys (
|
39
|
+
Split a `sysargs` list containing "and" keys (`+`)
|
25
40
|
into a list of individual `sysargs`.
|
26
41
|
"""
|
27
42
|
from meerschaum.config.static import STATIC_CONFIG
|
@@ -91,8 +106,8 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
|
|
91
106
|
for i, word in enumerate(sysargs):
|
92
107
|
is_sub_arg = False
|
93
108
|
if not found_begin_decorator:
|
94
|
-
found_begin_decorator = word.startswith(begin_decorator)
|
95
|
-
found_end_decorator = word.endswith(end_decorator)
|
109
|
+
found_begin_decorator = str(word).startswith(begin_decorator)
|
110
|
+
found_end_decorator = str(word).endswith(end_decorator)
|
96
111
|
|
97
112
|
if found_begin_decorator:
|
98
113
|
### check if sub arg is ever closed
|
@@ -102,15 +117,15 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
|
|
102
117
|
found_begin_decorator = False
|
103
118
|
elif found_end_decorator:
|
104
119
|
for a in sysargs[:i]:
|
105
|
-
if a.startswith(begin_decorator):
|
120
|
+
if str(a).startswith(begin_decorator):
|
106
121
|
is_sub_arg = True
|
107
122
|
found_begin_decorator = False
|
108
123
|
if is_sub_arg:
|
109
124
|
### remove decorators
|
110
125
|
sa = word
|
111
|
-
if sa.startswith(begin_decorator):
|
126
|
+
if str(sa).startswith(begin_decorator):
|
112
127
|
sa = sa[len(begin_decorator):]
|
113
|
-
if sa.endswith(end_decorator):
|
128
|
+
if str(sa).endswith(end_decorator):
|
114
129
|
sa = sa[:-1 * len(end_decorator)]
|
115
130
|
sub_arguments.append(sa)
|
116
131
|
### remove sub-argument from action list
|
@@ -129,7 +144,7 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
|
|
129
144
|
except Exception as e:
|
130
145
|
_action = []
|
131
146
|
for a in filtered_sysargs:
|
132
|
-
if a.startswith('-'):
|
147
|
+
if str(a).startswith('-'):
|
133
148
|
break
|
134
149
|
_action.append(a)
|
135
150
|
args_dict = {'action': _action, 'sysargs': sysargs}
|
@@ -249,20 +264,10 @@ def parse_dict_to_sysargs(
|
|
249
264
|
from meerschaum.config.static import STATIC_CONFIG
|
250
265
|
from meerschaum.utils.warnings import warn
|
251
266
|
|
252
|
-
and_key = STATIC_CONFIG['system']['arguments']['and_key']
|
253
|
-
if (line := args_dict.get('line', None)):
|
254
|
-
return shlex.split(line)
|
255
|
-
|
256
|
-
if (_sysargs := args_dict.get('sysargs', None)):
|
257
|
-
return _sysargs
|
258
|
-
|
259
267
|
action = args_dict.get('action', None)
|
260
|
-
if action and and_key in action:
|
261
|
-
warn(f"Cannot determine flags from chained actions:\n{args_dict}")
|
262
|
-
|
263
268
|
sysargs: List[str] = []
|
264
269
|
sysargs.extend(action or [])
|
265
|
-
allow_none_args = {'location_keys'}
|
270
|
+
allow_none_args = {'location_keys', 'begin', 'end', 'executor_keys'}
|
266
271
|
|
267
272
|
triggers = get_arguments_triggers()
|
268
273
|
|
@@ -273,12 +278,18 @@ def parse_dict_to_sysargs(
|
|
273
278
|
### Add boolean flags
|
274
279
|
if isinstance(args_dict[a], bool):
|
275
280
|
if args_dict[a] is True:
|
276
|
-
sysargs
|
281
|
+
sysargs.extend([t[0]])
|
277
282
|
else:
|
278
283
|
### Add list flags
|
279
284
|
if isinstance(args_dict[a], (list, tuple)):
|
280
285
|
if len(args_dict[a]) > 0:
|
281
|
-
sysargs
|
286
|
+
sysargs.extend(
|
287
|
+
[t[0]]
|
288
|
+
+ [
|
289
|
+
str(item)
|
290
|
+
for item in args_dict[a]
|
291
|
+
]
|
292
|
+
)
|
282
293
|
|
283
294
|
### Add dict flags
|
284
295
|
elif isinstance(args_dict[a], dict):
|
@@ -287,7 +298,7 @@ def parse_dict_to_sysargs(
|
|
287
298
|
|
288
299
|
### Account for None and other values
|
289
300
|
elif (args_dict[a] is not None) or (args_dict[a] is None and a in allow_none_args):
|
290
|
-
sysargs += [t[0], args_dict[a]]
|
301
|
+
sysargs += [t[0], str(args_dict[a])]
|
291
302
|
|
292
303
|
return sysargs
|
293
304
|
|
@@ -125,7 +125,7 @@ def parse_version(sysargs: List[str]):
|
|
125
125
|
return print(doc)
|
126
126
|
|
127
127
|
|
128
|
-
def parse_name(name_str: str) -> str:
|
128
|
+
def parse_name(name_str: str) -> Union[str, None]:
|
129
129
|
"""
|
130
130
|
Ensure that `--name` is not an empty string.
|
131
131
|
"""
|
@@ -215,13 +215,10 @@ groups['jobs'].add_argument(
|
|
215
215
|
help=("Restart a job if not stopped manually."),
|
216
216
|
)
|
217
217
|
groups['jobs'].add_argument(
|
218
|
-
'
|
219
|
-
help=("Create a job via systemd. Shorthand for `-e systemd`."),
|
220
|
-
)
|
221
|
-
groups['jobs'].add_argument(
|
222
|
-
'--executor-keys', '--executor', '-e', type=parse_executor_keys,
|
218
|
+
'-e', '--executor-keys', type=parse_executor_keys,
|
223
219
|
help=(
|
224
|
-
"Execute jobs
|
220
|
+
"Execute jobs locally or remotely. "
|
221
|
+
"Supported values are 'local', 'systemd', and 'api:{label}'."
|
225
222
|
),
|
226
223
|
)
|
227
224
|
groups['jobs'].add_argument(
|
@@ -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>
|
meerschaum/_internal/entry.py
CHANGED
@@ -32,7 +32,10 @@ if (_STATIC_CONFIG['environment']['systemd_log_path']) in os.environ:
|
|
32
32
|
if _systemd_stdin_path:
|
33
33
|
sys.stdin = _StdinFile(_systemd_stdin_path)
|
34
34
|
|
35
|
-
def entry(
|
35
|
+
def entry(
|
36
|
+
sysargs: Optional[List[str]] = None,
|
37
|
+
_patch_args: Optional[Dict[str, Any]] = None,
|
38
|
+
) -> SuccessTuple:
|
36
39
|
"""
|
37
40
|
Parse arguments and launch a Meerschaum action.
|
38
41
|
|
@@ -41,14 +44,23 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
41
44
|
A `SuccessTuple` indicating success.
|
42
45
|
"""
|
43
46
|
import shlex
|
47
|
+
import json
|
44
48
|
from meerschaum.utils.formatting import make_header
|
45
|
-
from meerschaum._internal.arguments import
|
49
|
+
from meerschaum._internal.arguments import (
|
50
|
+
parse_arguments,
|
51
|
+
split_chained_sysargs,
|
52
|
+
split_pipeline_sysargs,
|
53
|
+
)
|
46
54
|
from meerschaum.config.static import STATIC_CONFIG
|
47
55
|
if sysargs is None:
|
48
56
|
sysargs = []
|
49
57
|
if not isinstance(sysargs, list):
|
50
58
|
sysargs = shlex.split(sysargs)
|
51
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
|
+
|
52
64
|
has_daemon = '-d' in sysargs or '--daemon' in sysargs
|
53
65
|
has_start_job = sysargs[:2] == ['start', 'job']
|
54
66
|
chained_sysargs = (
|
@@ -56,10 +68,32 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
56
68
|
if has_daemon or has_start_job
|
57
69
|
else split_chained_sysargs(sysargs)
|
58
70
|
)
|
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
|
+
|
59
83
|
results: List[SuccessTuple] = []
|
60
84
|
|
61
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
|
+
|
62
94
|
args = parse_arguments(_sysargs)
|
95
|
+
if _patch_args:
|
96
|
+
args.update(_patch_args)
|
63
97
|
argparse_exception = args.get(
|
64
98
|
STATIC_CONFIG['system']['arguments']['failure_key'],
|
65
99
|
None,
|
@@ -76,7 +110,7 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
76
110
|
)
|
77
111
|
)
|
78
112
|
|
79
|
-
entry_success, entry_msg = entry_with_args(**args)
|
113
|
+
entry_success, entry_msg = entry_with_args(_patch_args=_patch_args, **args)
|
80
114
|
if not entry_success:
|
81
115
|
return entry_success, entry_msg
|
82
116
|
|
@@ -106,6 +140,7 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
106
140
|
|
107
141
|
def entry_with_args(
|
108
142
|
_actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
|
143
|
+
_patch_args: Optional[Dict[str, Any]] = None,
|
109
144
|
**kw
|
110
145
|
) -> SuccessTuple:
|
111
146
|
"""Execute a Meerschaum action with keyword arguments.
|
@@ -119,12 +154,15 @@ def entry_with_args(
|
|
119
154
|
from meerschaum.utils.venv import active_venvs, deactivate_venv
|
120
155
|
from meerschaum.config.static import STATIC_CONFIG
|
121
156
|
|
157
|
+
if _patch_args:
|
158
|
+
kw.update(_patch_args)
|
159
|
+
|
122
160
|
and_key = STATIC_CONFIG['system']['arguments']['and_key']
|
123
161
|
escaped_and_key = STATIC_CONFIG['system']['arguments']['escaped_and_key']
|
124
162
|
if and_key in (sysargs := kw.get('sysargs', [])):
|
125
163
|
if '-d' in sysargs or '--daemon' in sysargs:
|
126
164
|
sysargs = [(arg if arg != and_key else escaped_and_key) for arg in sysargs]
|
127
|
-
return entry(sysargs)
|
165
|
+
return entry(sysargs, _patch_args=_patch_args)
|
128
166
|
|
129
167
|
if kw.get('trace', None):
|
130
168
|
from meerschaum.utils.misc import debug_trace
|