meerschaum 2.2.5.dev3__py3-none-any.whl → 2.2.7__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 +4 -1
- meerschaum/__main__.py +10 -5
- meerschaum/_internal/arguments/_parser.py +13 -2
- meerschaum/_internal/docs/index.py +523 -26
- meerschaum/_internal/entry.py +13 -13
- meerschaum/_internal/shell/Shell.py +26 -22
- meerschaum/_internal/shell/updates.py +175 -0
- meerschaum/_internal/term/__init__.py +2 -2
- meerschaum/actions/bootstrap.py +13 -14
- meerschaum/actions/python.py +11 -8
- meerschaum/actions/register.py +149 -37
- meerschaum/actions/show.py +79 -71
- meerschaum/actions/stop.py +11 -11
- meerschaum/actions/sync.py +3 -3
- meerschaum/actions/upgrade.py +28 -36
- meerschaum/api/dash/callbacks/login.py +21 -13
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/routes/_login.py +5 -5
- meerschaum/api/routes/_pipes.py +20 -20
- meerschaum/config/__init__.py +8 -1
- meerschaum/config/_formatting.py +1 -0
- meerschaum/config/_paths.py +24 -2
- meerschaum/config/_shell.py +78 -66
- meerschaum/config/_version.py +1 -1
- meerschaum/config/paths.py +21 -2
- meerschaum/config/static/__init__.py +2 -0
- meerschaum/connectors/Connector.py +7 -2
- meerschaum/connectors/__init__.py +7 -5
- meerschaum/connectors/api/APIConnector.py +7 -2
- meerschaum/connectors/api/_actions.py +23 -31
- meerschaum/connectors/api/_misc.py +1 -1
- meerschaum/connectors/api/_request.py +13 -9
- meerschaum/connectors/api/_uri.py +5 -5
- meerschaum/core/Pipe/__init__.py +7 -3
- meerschaum/core/Pipe/_data.py +23 -15
- meerschaum/core/Pipe/_deduplicate.py +1 -1
- meerschaum/core/Pipe/_dtypes.py +5 -0
- meerschaum/core/Pipe/_fetch.py +18 -16
- meerschaum/core/Pipe/_sync.py +23 -15
- meerschaum/plugins/_Plugin.py +6 -6
- meerschaum/plugins/__init__.py +1 -1
- meerschaum/utils/daemon/Daemon.py +88 -129
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +14 -5
- meerschaum/utils/daemon/RotatingFile.py +23 -17
- meerschaum/utils/daemon/__init__.py +28 -21
- meerschaum/utils/dataframe.py +12 -4
- meerschaum/utils/debug.py +9 -15
- meerschaum/utils/formatting/__init__.py +92 -46
- meerschaum/utils/formatting/_jobs.py +47 -9
- meerschaum/utils/misc.py +117 -11
- meerschaum/utils/packages/__init__.py +28 -16
- meerschaum/utils/prompt.py +5 -0
- meerschaum/utils/schedule.py +21 -15
- meerschaum/utils/typing.py +1 -0
- meerschaum/utils/venv/__init__.py +5 -1
- meerschaum/utils/warnings.py +8 -1
- meerschaum/utils/yaml.py +2 -2
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/METADATA +1 -1
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/RECORD +65 -64
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/WHEEL +1 -1
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/LICENSE +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/NOTICE +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/top_level.txt +0 -0
- {meerschaum-2.2.5.dev3.dist-info → meerschaum-2.2.7.dist-info}/zip-safe +0 -0
meerschaum/_internal/entry.py
CHANGED
@@ -8,20 +8,15 @@ 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
|
11
|
+
from meerschaum.utils.typing import SuccessTuple, List, Optional, Dict, Callable, Any
|
12
12
|
|
13
13
|
def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
14
|
-
"""
|
15
|
-
|
16
|
-
|
17
|
-
Examples of action:
|
18
|
-
'show actions' -> ['actions']
|
19
|
-
'show' -> []
|
14
|
+
"""
|
15
|
+
Parse arguments and launch a Meerschaum action.
|
20
16
|
|
21
17
|
Returns
|
22
18
|
-------
|
23
|
-
A `SuccessTuple` indicating success.
|
24
|
-
|
19
|
+
A `SuccessTuple` indicating success.
|
25
20
|
"""
|
26
21
|
from meerschaum._internal.arguments import parse_arguments
|
27
22
|
from meerschaum.config.static import STATIC_CONFIG
|
@@ -51,9 +46,9 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
51
46
|
|
52
47
|
|
53
48
|
def entry_with_args(
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
_actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
|
50
|
+
**kw
|
51
|
+
) -> SuccessTuple:
|
57
52
|
"""Execute a Meerschaum action with keyword arguments.
|
58
53
|
Use `_entry()` for parsing sysargs before executing.
|
59
54
|
"""
|
@@ -96,7 +91,12 @@ def entry_with_args(
|
|
96
91
|
|
97
92
|
kw['action'] = remove_leading_action(kw['action'], _actions=_actions)
|
98
93
|
|
99
|
-
do_action = functools.partial(
|
94
|
+
do_action = functools.partial(
|
95
|
+
_do_action_wrapper,
|
96
|
+
action_function,
|
97
|
+
plugin_name,
|
98
|
+
**kw
|
99
|
+
)
|
100
100
|
if kw.get('schedule', None) and not skip_schedule:
|
101
101
|
from meerschaum.utils.schedule import schedule_function
|
102
102
|
from meerschaum.utils.misc import interval_str
|
@@ -95,8 +95,8 @@ def _insert_shell_actions(
|
|
95
95
|
setattr(_shell_class, 'complete_' + a, completer)
|
96
96
|
|
97
97
|
def _completer_wrapper(
|
98
|
-
|
99
|
-
|
98
|
+
target: Callable[[Any], List[str]]
|
99
|
+
) -> Callable[['meerschaum._internal.shell.Shell', str, str, int, int], Any]:
|
100
100
|
"""
|
101
101
|
Wrapper for `complete_` functions so they can instead use Meerschaum arguments.
|
102
102
|
"""
|
@@ -125,13 +125,13 @@ def _completer_wrapper(
|
|
125
125
|
|
126
126
|
|
127
127
|
def default_action_completer(
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
128
|
+
text: Optional[str] = None,
|
129
|
+
line: Optional[str] = None,
|
130
|
+
begin_index: Optional[int] = None,
|
131
|
+
end_index: Optional[int] = None,
|
132
|
+
action: Optional[List[str]] = None,
|
133
|
+
**kw: Any
|
134
|
+
) -> List[str]:
|
135
135
|
"""
|
136
136
|
Search for subactions by default. This may be overridden by each action.
|
137
137
|
"""
|
@@ -206,13 +206,11 @@ def get_shell_intro(with_color: bool = True) -> str:
|
|
206
206
|
"""
|
207
207
|
from meerschaum.utils.formatting import CHARSET, ANSI, colored
|
208
208
|
intro = get_config('shell', CHARSET, 'intro', patch=patch)
|
209
|
-
intro +=
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
]
|
215
|
-
) + 'v' + version
|
209
|
+
intro += (
|
210
|
+
'\n'
|
211
|
+
+ (' ' * (string_width(intro) - len('v' + version)))
|
212
|
+
+ f'v{version}'
|
213
|
+
)
|
216
214
|
|
217
215
|
if not with_color or not ANSI:
|
218
216
|
return intro
|
@@ -225,10 +223,10 @@ def get_shell_intro(with_color: bool = True) -> str:
|
|
225
223
|
|
226
224
|
class Shell(cmd.Cmd):
|
227
225
|
def __init__(
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
226
|
+
self,
|
227
|
+
actions: Optional[Dict[str, Any]] = None,
|
228
|
+
sysargs: Optional[List[str]] = None
|
229
|
+
):
|
232
230
|
"""
|
233
231
|
Customize the CLI from configuration
|
234
232
|
"""
|
@@ -297,19 +295,25 @@ class Shell(cmd.Cmd):
|
|
297
295
|
except Exception as e:
|
298
296
|
pass
|
299
297
|
|
298
|
+
### Finally, spawn the version update thread.
|
299
|
+
from meerschaum._internal.shell.updates import run_version_check_thread
|
300
|
+
self._update_thread = run_version_check_thread(debug=shell_attrs.get('debug', False))
|
301
|
+
|
302
|
+
|
300
303
|
def load_config(self, instance: Optional[str] = None):
|
301
304
|
"""
|
302
305
|
Set attributes from the shell configuration.
|
303
306
|
"""
|
304
307
|
from meerschaum.utils.misc import remove_ansi
|
305
308
|
from meerschaum.utils.formatting import CHARSET, ANSI, colored
|
306
|
-
|
309
|
+
from meerschaum._internal.shell.updates import get_update_message
|
310
|
+
|
307
311
|
if shell_attrs.get('intro', None) != '':
|
308
312
|
self.intro = (
|
309
313
|
get_shell_intro(with_color=False)
|
310
314
|
if shell_attrs.get('intro', None) != ''
|
311
315
|
else ""
|
312
|
-
)
|
316
|
+
) + get_update_message()
|
313
317
|
|
314
318
|
shell_attrs['intro'] = self.intro
|
315
319
|
shell_attrs['_prompt'] = get_config('shell', CHARSET, 'prompt', patch=patch)
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# vim:fenc=utf-8
|
4
|
+
|
5
|
+
"""
|
6
|
+
If configured, check `api:mrsm` for announcement messages.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import json
|
10
|
+
from datetime import datetime, timezone, timedelta
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
13
|
+
from meerschaum.utils.typing import Union, SuccessTuple, Optional
|
14
|
+
from meerschaum.config import get_config
|
15
|
+
from meerschaum.utils.formatting import CHARSET, ANSI, colored
|
16
|
+
from meerschaum.utils.misc import string_width, remove_ansi
|
17
|
+
from meerschaum.config.paths import (
|
18
|
+
UPDATES_LOCK_PATH,
|
19
|
+
UPDATES_CACHE_PATH,
|
20
|
+
)
|
21
|
+
from meerschaum.utils.threading import Thread
|
22
|
+
|
23
|
+
|
24
|
+
def cache_remote_version(debug: bool = False) -> SuccessTuple:
|
25
|
+
"""
|
26
|
+
Fetch and cache the latest version if available.
|
27
|
+
"""
|
28
|
+
allow_update_check = get_config('shell', 'updates', 'check_remote')
|
29
|
+
if not allow_update_check:
|
30
|
+
return True, "Update checks are disabled."
|
31
|
+
|
32
|
+
refresh_minutes = get_config('shell', 'updates', 'refresh_minutes')
|
33
|
+
update_delta = timedelta(minutes=refresh_minutes)
|
34
|
+
|
35
|
+
if UPDATES_CACHE_PATH.exists():
|
36
|
+
try:
|
37
|
+
with open(UPDATES_CACHE_PATH, 'r', encoding='utf8') as f:
|
38
|
+
cache_dict = json.load(f)
|
39
|
+
except Exception:
|
40
|
+
cache_dict = {}
|
41
|
+
else:
|
42
|
+
cache_dict = {}
|
43
|
+
|
44
|
+
now = datetime.now(timezone.utc)
|
45
|
+
last_check_ts_str = cache_dict.get('last_check_ts')
|
46
|
+
last_check_ts = datetime.fromisoformat(last_check_ts_str) if last_check_ts_str else None
|
47
|
+
|
48
|
+
need_update = (
|
49
|
+
last_check_ts_str is None
|
50
|
+
or ((now - last_check_ts) >= update_delta)
|
51
|
+
)
|
52
|
+
|
53
|
+
if not need_update:
|
54
|
+
return True, "No updates are needed."
|
55
|
+
|
56
|
+
try:
|
57
|
+
conn = mrsm.get_connector('api:mrsm')
|
58
|
+
remote_version = conn.get_mrsm_version(debug=debug, timeout=3)
|
59
|
+
except Exception:
|
60
|
+
remote_version = None
|
61
|
+
|
62
|
+
if remote_version is None:
|
63
|
+
return False, "Could not determine remote version."
|
64
|
+
|
65
|
+
with open(UPDATES_CACHE_PATH, 'w+', encoding='utf-8') as f:
|
66
|
+
json.dump(
|
67
|
+
{
|
68
|
+
'last_check_ts': now.isoformat(),
|
69
|
+
'remote_version': remote_version,
|
70
|
+
},
|
71
|
+
f,
|
72
|
+
)
|
73
|
+
|
74
|
+
return True, "Updated remote version cache."
|
75
|
+
|
76
|
+
|
77
|
+
def run_version_check_thread(debug: bool = False) -> Union[Thread, None]:
|
78
|
+
"""
|
79
|
+
Run the version update check in a separate thread.
|
80
|
+
"""
|
81
|
+
allow_update_check = get_config('shell', 'updates', 'check_remote')
|
82
|
+
if not allow_update_check:
|
83
|
+
return None
|
84
|
+
|
85
|
+
thread = Thread(
|
86
|
+
target=cache_remote_version,
|
87
|
+
daemon=True,
|
88
|
+
kwargs={'debug': debug},
|
89
|
+
)
|
90
|
+
thread.start()
|
91
|
+
return thread
|
92
|
+
|
93
|
+
|
94
|
+
_remote_version: Optional[str] = None
|
95
|
+
def get_remote_version_from_cache() -> Optional[str]:
|
96
|
+
"""
|
97
|
+
Return the version string from the local cache file.
|
98
|
+
"""
|
99
|
+
global _remote_version
|
100
|
+
try:
|
101
|
+
with open(UPDATES_CACHE_PATH, 'r', encoding='utf-8') as f:
|
102
|
+
cache_dict = json.load(f)
|
103
|
+
except Exception:
|
104
|
+
return None
|
105
|
+
|
106
|
+
_remote_version = cache_dict.get('remote_version')
|
107
|
+
return _remote_version
|
108
|
+
|
109
|
+
|
110
|
+
_out_of_date: Optional[bool] = None
|
111
|
+
def mrsm_out_of_date() -> bool:
|
112
|
+
"""
|
113
|
+
Determine whether to print the upgrade message.
|
114
|
+
"""
|
115
|
+
global _out_of_date
|
116
|
+
if _out_of_date is not None:
|
117
|
+
return _out_of_date
|
118
|
+
|
119
|
+
### NOTE: Remote version is cached asynchronously.
|
120
|
+
if not UPDATES_CACHE_PATH.exists():
|
121
|
+
return False
|
122
|
+
|
123
|
+
remote_version_str = get_remote_version_from_cache()
|
124
|
+
|
125
|
+
packaging_version = mrsm.attempt_import('packaging.version')
|
126
|
+
current_version = packaging_version.parse(mrsm.__version__)
|
127
|
+
remote_version = packaging_version.parse(remote_version_str)
|
128
|
+
|
129
|
+
_out_of_date = remote_version > current_version
|
130
|
+
return _out_of_date
|
131
|
+
|
132
|
+
|
133
|
+
def get_update_message() -> str:
|
134
|
+
"""
|
135
|
+
Return the formatted message for when the current version is behind the latest release.
|
136
|
+
"""
|
137
|
+
if not mrsm_out_of_date():
|
138
|
+
return ''
|
139
|
+
|
140
|
+
intro = get_config('shell', CHARSET, 'intro')
|
141
|
+
update_message = get_config('shell', CHARSET, 'update_message')
|
142
|
+
remote_version = get_remote_version_from_cache()
|
143
|
+
if not remote_version:
|
144
|
+
return ''
|
145
|
+
|
146
|
+
intro_width = string_width(intro)
|
147
|
+
msg_width = string_width(update_message)
|
148
|
+
update_left_padding = ' ' * ((intro_width - msg_width) // 2)
|
149
|
+
|
150
|
+
update_line = (
|
151
|
+
colored(
|
152
|
+
update_message,
|
153
|
+
*get_config('shell', 'ansi', 'update_message', 'color')
|
154
|
+
) if ANSI
|
155
|
+
else update_message
|
156
|
+
)
|
157
|
+
update_instruction = (
|
158
|
+
colored("Run ", 'white')
|
159
|
+
+ colored("upgrade mrsm", 'green')
|
160
|
+
+ colored(" to install ", 'white')
|
161
|
+
+ colored(f'v{remote_version}', 'yellow')
|
162
|
+
+ '.'
|
163
|
+
)
|
164
|
+
update_instruction_clean = remove_ansi(update_instruction)
|
165
|
+
instruction_width = string_width(update_instruction_clean)
|
166
|
+
instruction_left_padding = ' ' * ((intro_width - instruction_width) // 2)
|
167
|
+
|
168
|
+
return (
|
169
|
+
'\n\n'
|
170
|
+
+ update_left_padding
|
171
|
+
+ update_line
|
172
|
+
+ '\n'
|
173
|
+
+ instruction_left_padding
|
174
|
+
+ update_instruction
|
175
|
+
)
|
@@ -22,7 +22,7 @@ tornado, tornado_ioloop, terminado = attempt_import(
|
|
22
22
|
|
23
23
|
def get_webterm_app_and_manager() -> Tuple[
|
24
24
|
tornado.web.Application,
|
25
|
-
terminado.UniqueTermManager,
|
25
|
+
terminado.UniqueTermManager,
|
26
26
|
]:
|
27
27
|
"""
|
28
28
|
Construct the Tornado web app and term manager from the provided sysargs.
|
@@ -47,7 +47,7 @@ def get_webterm_app_and_manager() -> Tuple[
|
|
47
47
|
{'term_manager': term_manager}
|
48
48
|
),
|
49
49
|
(
|
50
|
-
r"/",
|
50
|
+
r"/",
|
51
51
|
TermPageHandler
|
52
52
|
),
|
53
53
|
]
|
meerschaum/actions/bootstrap.py
CHANGED
@@ -221,18 +221,17 @@ def _bootstrap_pipes(
|
|
221
221
|
return (successes > 0), msg
|
222
222
|
|
223
223
|
def _bootstrap_connectors(
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
224
|
+
action: Optional[List[str]] = None,
|
225
|
+
connector_keys: Optional[List[str]] = None,
|
226
|
+
yes: bool = False,
|
227
|
+
force: bool = False,
|
228
|
+
noask: bool = False,
|
229
|
+
debug: bool = False,
|
230
|
+
return_keys: bool = False,
|
231
|
+
**kw: Any
|
232
|
+
) -> Union[SuccessTuple, Tuple[str, str]]:
|
233
233
|
"""
|
234
234
|
Prompt the user for the details necessary to create a Connector.
|
235
|
-
|
236
235
|
"""
|
237
236
|
from meerschaum.connectors.parse import is_valid_connector_keys
|
238
237
|
from meerschaum.connectors import connectors, get_connector, types, custom_types
|
@@ -386,10 +385,10 @@ def _bootstrap_connectors(
|
|
386
385
|
|
387
386
|
|
388
387
|
def _bootstrap_plugins(
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
388
|
+
action: Optional[List[str]] = None,
|
389
|
+
debug: bool = False,
|
390
|
+
**kwargs: Any
|
391
|
+
) -> SuccessTuple:
|
393
392
|
"""
|
394
393
|
Launch an interactive wizard to guide the user to creating a new plugin.
|
395
394
|
"""
|
meerschaum/actions/python.py
CHANGED
@@ -9,14 +9,14 @@ from __future__ import annotations
|
|
9
9
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional
|
10
10
|
|
11
11
|
def python(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
action: Optional[List[str]] = None,
|
13
|
+
sub_args: Optional[List[str]] = None,
|
14
|
+
nopretty: bool = False,
|
15
|
+
noask: bool = False,
|
16
|
+
venv: Optional[str] = None,
|
17
|
+
debug: bool = False,
|
18
|
+
**kw: Any
|
19
|
+
) -> SuccessTuple:
|
20
20
|
"""
|
21
21
|
Launch a virtual environment's Python interpreter with Meerschaum imported.
|
22
22
|
You may pass flags to the Python binary by surrounding each flag with `[]`.
|
@@ -56,6 +56,9 @@ def python(
|
|
56
56
|
if action is None:
|
57
57
|
action = []
|
58
58
|
|
59
|
+
if noask:
|
60
|
+
nopretty = True
|
61
|
+
|
59
62
|
joined_actions = (
|
60
63
|
["import meerschaum as mrsm"]
|
61
64
|
if venv is None and not sub_args
|
meerschaum/actions/register.py
CHANGED
@@ -7,12 +7,13 @@ Register new Pipes. Requires the API to be running.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
+
import meerschaum as mrsm
|
10
11
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Dict
|
11
12
|
|
12
13
|
def register(
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
action: Optional[List[str]] = None,
|
15
|
+
**kw: Any
|
16
|
+
) -> SuccessTuple:
|
16
17
|
"""
|
17
18
|
Register new items (pipes, plugins, users).
|
18
19
|
|
@@ -23,22 +24,25 @@ def register(
|
|
23
24
|
'pipes' : _register_pipes,
|
24
25
|
'plugins' : _register_plugins,
|
25
26
|
'users' : _register_users,
|
27
|
+
'connectors': _register_connectors,
|
26
28
|
}
|
27
29
|
return choose_subaction(action, options, **kw)
|
28
30
|
|
29
31
|
|
30
32
|
def _complete_register(
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
action: Optional[List[str]] = None,
|
34
|
+
**kw: Any
|
35
|
+
) -> List[str]:
|
34
36
|
"""
|
35
37
|
Override the default Meerschaum `complete_` function.
|
36
38
|
"""
|
37
39
|
if action is None:
|
38
40
|
action = []
|
39
41
|
options = {
|
40
|
-
'plugin'
|
41
|
-
'plugins'
|
42
|
+
'plugin': _complete_register_plugins,
|
43
|
+
'plugins': _complete_register_plugins,
|
44
|
+
'connector': _complete_register_connectors,
|
45
|
+
'connectors': _complete_register_connectors,
|
42
46
|
}
|
43
47
|
|
44
48
|
if len(action) > 0 and action[0] in options:
|
@@ -51,14 +55,14 @@ def _complete_register(
|
|
51
55
|
|
52
56
|
|
53
57
|
def _register_pipes(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
connector_keys: Optional[List[str]] = None,
|
59
|
+
metric_keys: Optional[List[str]] = None,
|
60
|
+
location_keys: Optional[List[str]] = None,
|
61
|
+
params: Optional[Dict[str, Any]] = None,
|
62
|
+
tags: Optional[List[str]] = None,
|
63
|
+
debug: bool = False,
|
64
|
+
**kw: Any
|
65
|
+
) -> SuccessTuple:
|
62
66
|
"""
|
63
67
|
Create and register Pipe objects.
|
64
68
|
|
@@ -147,15 +151,18 @@ def _register_pipes(
|
|
147
151
|
|
148
152
|
|
149
153
|
def _register_plugins(
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
154
|
+
action: Optional[List[str]] = None,
|
155
|
+
repository: Optional[str] = None,
|
156
|
+
shell: bool = False,
|
157
|
+
debug: bool = False,
|
158
|
+
yes: bool = False,
|
159
|
+
noask: bool = False,
|
160
|
+
force: bool = False,
|
161
|
+
**kw: Any
|
162
|
+
) -> SuccessTuple:
|
163
|
+
"""
|
164
|
+
Upload plugins to an API instance (repository).
|
165
|
+
"""
|
159
166
|
from meerschaum.utils.debug import dprint
|
160
167
|
from meerschaum.plugins import reload_plugins, get_plugins_names
|
161
168
|
from meerschaum.connectors.parse import parse_repo_keys
|
@@ -196,14 +203,23 @@ def _register_plugins(
|
|
196
203
|
successes = {}
|
197
204
|
|
198
205
|
for name, plugin in plugins_to_register.items():
|
199
|
-
desc = None
|
200
206
|
plugin.attributes = repo_connector.get_plugin_attributes(plugin, debug=debug)
|
201
207
|
if plugin.attributes is None:
|
202
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
|
+
|
203
219
|
question = f"Would you like to add a description to plugin '{name}'?"
|
204
|
-
if
|
220
|
+
if desc:
|
205
221
|
info(f"Found existing description for plugin '{plugin}':")
|
206
|
-
print(
|
222
|
+
print(desc)
|
207
223
|
question = (
|
208
224
|
"Would you like to overwrite this description?\n"
|
209
225
|
+ "To edit the existing text, visit /dash/plugins for this repository."
|
@@ -213,9 +229,14 @@ def _register_plugins(
|
|
213
229
|
default='n',
|
214
230
|
yes=yes
|
215
231
|
):
|
216
|
-
info('Press (Esc + Enter) to submit
|
232
|
+
info('Press (Esc + Enter) to submit, (CTRL + C) to cancel.')
|
217
233
|
try:
|
218
|
-
desc = prompt(
|
234
|
+
desc = prompt(
|
235
|
+
'',
|
236
|
+
multiline=True,
|
237
|
+
icon=False,
|
238
|
+
default_editable=desc.lstrip().rstrip(),
|
239
|
+
)
|
219
240
|
except KeyboardInterrupt:
|
220
241
|
desc = None
|
221
242
|
if desc == '':
|
@@ -246,17 +267,19 @@ def _register_plugins(
|
|
246
267
|
reload_plugins(debug=debug)
|
247
268
|
return total_success > 0, msg
|
248
269
|
|
270
|
+
|
249
271
|
def _complete_register_plugins(*args, **kw):
|
250
272
|
from meerschaum.actions.uninstall import _complete_uninstall_plugins
|
251
273
|
return _complete_uninstall_plugins(*args, **kw)
|
252
274
|
|
275
|
+
|
253
276
|
def _register_users(
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
277
|
+
action: Optional[List[str]] = None,
|
278
|
+
mrsm_instance: Optional[str] = None,
|
279
|
+
shell: bool = False,
|
280
|
+
debug: bool = False,
|
281
|
+
**kw: Any
|
282
|
+
) -> SuccessTuple:
|
260
283
|
"""
|
261
284
|
Register a new user to a Meerschaum instance.
|
262
285
|
"""
|
@@ -294,7 +317,7 @@ def _register_users(
|
|
294
317
|
nonregistered_users.append(user)
|
295
318
|
|
296
319
|
### prompt for passwords and emails, then try to register
|
297
|
-
success =
|
320
|
+
success = {}
|
298
321
|
successfully_registered_users = set()
|
299
322
|
for _user in nonregistered_users:
|
300
323
|
try:
|
@@ -337,6 +360,95 @@ def _register_users(
|
|
337
360
|
)
|
338
361
|
return succeeded > 0, msg
|
339
362
|
|
363
|
+
|
364
|
+
def _register_connectors(
|
365
|
+
action: Optional[List[str]] = None,
|
366
|
+
connector_keys: Optional[List[str]] = None,
|
367
|
+
params: Optional[Dict[str, Any]] = None,
|
368
|
+
**kwargs: Any
|
369
|
+
) -> SuccessTuple:
|
370
|
+
"""
|
371
|
+
Create new connectors programmatically with `--params`.
|
372
|
+
See `bootstrap connector`.
|
373
|
+
|
374
|
+
Examples:
|
375
|
+
|
376
|
+
mrsm register connector sql:tmp --params 'uri:sqlite:////tmp/tmp.db'
|
377
|
+
|
378
|
+
mrsm register connector -c sql:new --params '{"database": "/tmp/new.db"}'
|
379
|
+
"""
|
380
|
+
from meerschaum.config import get_config, write_config
|
381
|
+
from meerschaum.utils.prompt import yes_no
|
382
|
+
from meerschaum.utils.warnings import warn
|
383
|
+
all_keys = (action or []) + (connector_keys or [])
|
384
|
+
if len(all_keys) != 1:
|
385
|
+
return (
|
386
|
+
False,
|
387
|
+
"Provide one pair of keys for the connector to be registered."
|
388
|
+
)
|
389
|
+
|
390
|
+
keys = all_keys[0]
|
391
|
+
|
392
|
+
if keys.count(':') != 1:
|
393
|
+
return False, "Connector keys must be in the format `type:label`."
|
394
|
+
|
395
|
+
type_, label = keys.split(':', maxsplit=1)
|
396
|
+
mrsm_config = get_config('meerschaum')
|
397
|
+
if 'connectors' not in mrsm_config:
|
398
|
+
mrsm_config['connectors'] = {}
|
399
|
+
|
400
|
+
if type_ not in mrsm_config['connectors']:
|
401
|
+
mrsm_config['connectors'] = {}
|
402
|
+
|
403
|
+
is_new = True
|
404
|
+
if label in mrsm_config['connectors'][type_]:
|
405
|
+
rich_table, rich_json, rich_box = mrsm.attempt_import(
|
406
|
+
'rich.table',
|
407
|
+
'rich.json',
|
408
|
+
'rich.box',
|
409
|
+
)
|
410
|
+
existing_params = mrsm_config['connectors'][type_][label]
|
411
|
+
if existing_params == params:
|
412
|
+
return True, "Connector exists, nothing to do."
|
413
|
+
|
414
|
+
table = rich_table.Table(box=rich_box.MINIMAL)
|
415
|
+
table.add_column('Existing Parameters')
|
416
|
+
table.add_column('New Parameters')
|
417
|
+
table.add_row(
|
418
|
+
rich_json.JSON.from_data(existing_params),
|
419
|
+
rich_json.JSON.from_data(params or {}),
|
420
|
+
)
|
421
|
+
|
422
|
+
mrsm.pprint(table)
|
423
|
+
warn(f"Connector '{keys}' already exists.", stack=False)
|
424
|
+
if not yes_no(
|
425
|
+
f"Do you want to overwrite connector '{keys}'?",
|
426
|
+
default='n',
|
427
|
+
**kwargs
|
428
|
+
):
|
429
|
+
return False, "Nothing was changed."
|
430
|
+
|
431
|
+
is_new = False
|
432
|
+
|
433
|
+
mrsm_config['connectors'][type_][label] = params
|
434
|
+
if not write_config({'meerschaum': mrsm_config}):
|
435
|
+
return False, "Failed to update configuration."
|
436
|
+
|
437
|
+
msg = (
|
438
|
+
"Successfully "
|
439
|
+
+ ("registered" if is_new else "updated")
|
440
|
+
+ f" connector '{keys}'."
|
441
|
+
)
|
442
|
+
return True, msg
|
443
|
+
|
444
|
+
|
445
|
+
def _complete_register_connectors(
|
446
|
+
action: Optional[List[str]] = None, **kw: Any
|
447
|
+
) -> List[str]:
|
448
|
+
from meerschaum.actions.show import _complete_show_connectors
|
449
|
+
return _complete_show_connectors(action)
|
450
|
+
|
451
|
+
|
340
452
|
### NOTE: This must be the final statement of the module.
|
341
453
|
### Any subactions added below these lines will not
|
342
454
|
### be added to the `help` docstring.
|