meerschaum 2.9.5__py3-none-any.whl → 3.0.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 +5 -2
- meerschaum/_internal/__init__.py +1 -0
- meerschaum/_internal/arguments/_parse_arguments.py +4 -4
- meerschaum/_internal/arguments/_parser.py +33 -4
- meerschaum/_internal/cli/__init__.py +6 -0
- meerschaum/_internal/cli/daemons.py +103 -0
- meerschaum/_internal/cli/entry.py +220 -0
- meerschaum/_internal/cli/workers.py +435 -0
- meerschaum/_internal/docs/index.py +48 -2
- meerschaum/_internal/entry.py +50 -14
- meerschaum/_internal/shell/Shell.py +121 -29
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +359 -0
- meerschaum/_internal/term/TermPageHandler.py +1 -2
- meerschaum/_internal/term/__init__.py +40 -6
- meerschaum/_internal/term/tools.py +33 -8
- meerschaum/actions/__init__.py +6 -4
- meerschaum/actions/api.py +53 -13
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/bootstrap.py +8 -8
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +171 -25
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +143 -6
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +184 -31
- meerschaum/actions/start.py +166 -17
- meerschaum/actions/stop.py +38 -2
- meerschaum/actions/sync.py +7 -2
- meerschaum/actions/tag.py +9 -8
- meerschaum/actions/verify.py +5 -8
- meerschaum/api/__init__.py +45 -15
- meerschaum/api/_events.py +46 -4
- meerschaum/api/_oauth2.py +162 -9
- meerschaum/api/_tokens.py +102 -0
- meerschaum/api/dash/__init__.py +0 -3
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/custom.py +4 -3
- meerschaum/api/dash/callbacks/dashboard.py +198 -118
- meerschaum/api/dash/callbacks/jobs.py +14 -7
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +194 -14
- meerschaum/api/dash/callbacks/plugins.py +0 -1
- meerschaum/api/dash/callbacks/register.py +10 -3
- meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
- meerschaum/api/dash/callbacks/tokens.py +389 -0
- meerschaum/api/dash/components.py +36 -15
- meerschaum/api/dash/jobs.py +1 -1
- meerschaum/api/dash/keys.py +35 -93
- meerschaum/api/dash/pages/__init__.py +2 -1
- meerschaum/api/dash/pages/dashboard.py +1 -20
- meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +16 -5
- meerschaum/api/dash/pages/settings/password_reset.py +1 -1
- meerschaum/api/dash/pages/tokens.py +53 -0
- meerschaum/api/dash/pipes.py +382 -95
- meerschaum/api/dash/sessions.py +12 -0
- meerschaum/api/dash/tokens.py +603 -0
- meerschaum/api/dash/websockets.py +1 -1
- meerschaum/api/dash/webterm.py +18 -6
- meerschaum/api/models/__init__.py +23 -3
- meerschaum/api/models/_actions.py +22 -0
- meerschaum/api/models/_pipes.py +91 -7
- meerschaum/api/models/_tokens.py +81 -0
- meerschaum/api/resources/static/js/terminado.js +3 -0
- meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
- meerschaum/api/resources/templates/termpage.html +13 -0
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +3 -4
- meerschaum/api/routes/_connectors.py +3 -7
- meerschaum/api/routes/_jobs.py +26 -35
- meerschaum/api/routes/_login.py +120 -15
- meerschaum/api/routes/_misc.py +5 -10
- meerschaum/api/routes/_pipes.py +178 -143
- meerschaum/api/routes/_plugins.py +38 -28
- meerschaum/api/routes/_tokens.py +236 -0
- meerschaum/api/routes/_users.py +47 -35
- meerschaum/api/routes/_version.py +3 -3
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +100 -30
- meerschaum/config/_default.py +132 -64
- meerschaum/config/_edit.py +38 -32
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +10 -8
- meerschaum/config/_paths.py +133 -13
- meerschaum/config/_read_config.py +87 -36
- meerschaum/config/_sync.py +6 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +37 -15
- meerschaum/config/static.py +18 -0
- meerschaum/connectors/_Connector.py +11 -6
- meerschaum/connectors/__init__.py +41 -22
- meerschaum/connectors/api/_APIConnector.py +34 -6
- meerschaum/connectors/api/_actions.py +2 -2
- meerschaum/connectors/api/_jobs.py +12 -1
- meerschaum/connectors/api/_login.py +33 -7
- meerschaum/connectors/api/_misc.py +2 -2
- meerschaum/connectors/api/_pipes.py +23 -32
- meerschaum/connectors/api/_plugins.py +2 -2
- meerschaum/connectors/api/_request.py +1 -1
- meerschaum/connectors/api/_tokens.py +146 -0
- meerschaum/connectors/api/_users.py +70 -58
- meerschaum/connectors/instance/_InstanceConnector.py +83 -0
- meerschaum/connectors/instance/__init__.py +10 -0
- meerschaum/connectors/instance/_pipes.py +442 -0
- meerschaum/connectors/instance/_plugins.py +159 -0
- meerschaum/connectors/instance/_tokens.py +317 -0
- meerschaum/connectors/instance/_users.py +188 -0
- meerschaum/connectors/parse.py +5 -2
- meerschaum/connectors/sql/_SQLConnector.py +22 -5
- meerschaum/connectors/sql/_cli.py +12 -11
- meerschaum/connectors/sql/_create_engine.py +12 -168
- meerschaum/connectors/sql/_fetch.py +2 -18
- meerschaum/connectors/sql/_pipes.py +295 -278
- meerschaum/connectors/sql/_plugins.py +29 -0
- meerschaum/connectors/sql/_sql.py +46 -21
- meerschaum/connectors/sql/_users.py +36 -2
- meerschaum/connectors/sql/tables/__init__.py +254 -122
- meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
- meerschaum/connectors/valkey/_pipes.py +60 -31
- meerschaum/connectors/valkey/_plugins.py +2 -26
- meerschaum/core/Pipe/__init__.py +115 -85
- meerschaum/core/Pipe/_attributes.py +425 -124
- meerschaum/core/Pipe/_bootstrap.py +54 -24
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +96 -68
- meerschaum/core/Pipe/_deduplicate.py +0 -13
- meerschaum/core/Pipe/_delete.py +12 -21
- meerschaum/core/Pipe/_drop.py +11 -23
- meerschaum/core/Pipe/_dtypes.py +49 -19
- meerschaum/core/Pipe/_edit.py +14 -4
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_show.py +5 -5
- meerschaum/core/Pipe/_sync.py +123 -204
- meerschaum/core/Pipe/_verify.py +4 -4
- meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
- meerschaum/core/Plugin/__init__.py +1 -1
- meerschaum/core/Token/_Token.py +220 -0
- meerschaum/core/Token/__init__.py +12 -0
- meerschaum/core/User/_User.py +35 -10
- meerschaum/core/User/__init__.py +9 -1
- meerschaum/core/__init__.py +1 -0
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +149 -38
- meerschaum/jobs/__init__.py +3 -2
- meerschaum/jobs/systemd.py +8 -3
- meerschaum/models/__init__.py +35 -0
- meerschaum/models/pipes.py +247 -0
- meerschaum/models/tokens.py +38 -0
- meerschaum/models/users.py +26 -0
- meerschaum/plugins/__init__.py +301 -88
- meerschaum/plugins/bootstrap.py +510 -4
- meerschaum/utils/_get_pipes.py +97 -30
- meerschaum/utils/daemon/Daemon.py +199 -43
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
- meerschaum/utils/daemon/RotatingFile.py +63 -36
- meerschaum/utils/daemon/StdinFile.py +53 -13
- meerschaum/utils/daemon/__init__.py +47 -6
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/dataframe.py +479 -81
- meerschaum/utils/debug.py +49 -19
- meerschaum/utils/dtypes/__init__.py +476 -34
- meerschaum/utils/dtypes/sql.py +369 -29
- meerschaum/utils/formatting/__init__.py +5 -2
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +52 -50
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +44 -18
- meerschaum/utils/misc.py +268 -186
- meerschaum/utils/packages/__init__.py +25 -40
- meerschaum/utils/packages/_packages.py +42 -34
- meerschaum/utils/pipes.py +213 -0
- meerschaum/utils/process.py +2 -2
- meerschaum/utils/prompt.py +175 -144
- meerschaum/utils/schedule.py +2 -1
- meerschaum/utils/sql.py +134 -47
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/typing.py +1 -4
- meerschaum/utils/venv/_Venv.py +2 -2
- meerschaum/utils/venv/__init__.py +7 -7
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
- meerschaum-3.0.0.dist-info/RECORD +289 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
- meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
- meerschaum/api/models/_interfaces.py +0 -15
- meerschaum/api/models/_locations.py +0 -15
- meerschaum/api/models/_metrics.py +0 -15
- meerschaum/config/_environment.py +0 -145
- meerschaum/config/static/__init__.py +0 -186
- meerschaum-2.9.5.dist-info/RECORD +0 -263
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define the interface for instance connectors.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
import abc
|
11
|
+
from typing import Any, Union, Dict, List, Tuple, Optional
|
12
|
+
|
13
|
+
import meerschaum as mrsm
|
14
|
+
from meerschaum.connectors._Connector import Connector
|
15
|
+
|
16
|
+
|
17
|
+
class InstanceConnector(Connector):
|
18
|
+
"""
|
19
|
+
Instance connectors define the interface for managing pipes and provide methods
|
20
|
+
for management of users, plugins, tokens, and other metadata built atop pipes.
|
21
|
+
"""
|
22
|
+
|
23
|
+
IS_INSTANCE: bool = True
|
24
|
+
IS_THREAD_SAFE: bool = False
|
25
|
+
|
26
|
+
from ._users import (
|
27
|
+
get_users_pipe,
|
28
|
+
register_user,
|
29
|
+
get_user_id,
|
30
|
+
get_username,
|
31
|
+
get_users,
|
32
|
+
edit_user,
|
33
|
+
delete_user,
|
34
|
+
get_user_password_hash,
|
35
|
+
get_user_type,
|
36
|
+
get_user_attributes,
|
37
|
+
)
|
38
|
+
|
39
|
+
from ._plugins import (
|
40
|
+
get_plugins_pipe,
|
41
|
+
register_plugin,
|
42
|
+
get_plugin_user_id,
|
43
|
+
delete_plugin,
|
44
|
+
get_plugin_id,
|
45
|
+
get_plugin_version,
|
46
|
+
get_plugins,
|
47
|
+
get_plugin_user_id,
|
48
|
+
get_plugin_username,
|
49
|
+
get_plugin_attributes,
|
50
|
+
)
|
51
|
+
|
52
|
+
from ._tokens import (
|
53
|
+
get_tokens_pipe,
|
54
|
+
register_token,
|
55
|
+
edit_token,
|
56
|
+
invalidate_token,
|
57
|
+
delete_token,
|
58
|
+
get_token,
|
59
|
+
get_tokens,
|
60
|
+
get_token_model,
|
61
|
+
get_token_secret_hash,
|
62
|
+
token_exists,
|
63
|
+
get_token_scopes,
|
64
|
+
)
|
65
|
+
|
66
|
+
from ._pipes import (
|
67
|
+
register_pipe,
|
68
|
+
get_pipe_attributes,
|
69
|
+
get_pipe_id,
|
70
|
+
edit_pipe,
|
71
|
+
delete_pipe,
|
72
|
+
fetch_pipes_keys,
|
73
|
+
pipe_exists,
|
74
|
+
drop_pipe,
|
75
|
+
drop_pipe_indices,
|
76
|
+
sync_pipe,
|
77
|
+
create_pipe_indices,
|
78
|
+
clear_pipe,
|
79
|
+
get_pipe_data,
|
80
|
+
get_sync_time,
|
81
|
+
get_pipe_columns_types,
|
82
|
+
get_pipe_columns_indices,
|
83
|
+
)
|
@@ -0,0 +1,442 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define function signatures for pipes' methods.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
import abc
|
11
|
+
from typing import Any, Union, Dict, List, Tuple, Optional
|
12
|
+
from datetime import datetime
|
13
|
+
|
14
|
+
import meerschaum as mrsm
|
15
|
+
|
16
|
+
@abc.abstractmethod
|
17
|
+
def register_pipe(
|
18
|
+
self,
|
19
|
+
pipe: mrsm.Pipe,
|
20
|
+
debug: bool = False,
|
21
|
+
**kwargs: Any
|
22
|
+
) -> mrsm.SuccessTuple:
|
23
|
+
"""
|
24
|
+
Insert the pipe's attributes into the internal `pipes` table.
|
25
|
+
|
26
|
+
Parameters
|
27
|
+
----------
|
28
|
+
pipe: mrsm.Pipe
|
29
|
+
The pipe to be registered.
|
30
|
+
|
31
|
+
Returns
|
32
|
+
-------
|
33
|
+
A `SuccessTuple` of the result.
|
34
|
+
"""
|
35
|
+
|
36
|
+
@abc.abstractmethod
|
37
|
+
def get_pipe_attributes(
|
38
|
+
self,
|
39
|
+
pipe: mrsm.Pipe,
|
40
|
+
debug: bool = False,
|
41
|
+
**kwargs: Any
|
42
|
+
) -> Dict[str, Any]:
|
43
|
+
"""
|
44
|
+
Return the pipe's document from the internal `pipes` table.
|
45
|
+
|
46
|
+
Parameters
|
47
|
+
----------
|
48
|
+
pipe: mrsm.Pipe
|
49
|
+
The pipe whose attributes should be retrieved.
|
50
|
+
|
51
|
+
Returns
|
52
|
+
-------
|
53
|
+
The document that matches the keys of the pipe.
|
54
|
+
"""
|
55
|
+
|
56
|
+
@abc.abstractmethod
|
57
|
+
def get_pipe_id(
|
58
|
+
self,
|
59
|
+
pipe: mrsm.Pipe,
|
60
|
+
debug: bool = False,
|
61
|
+
**kwargs: Any
|
62
|
+
) -> Union[str, int, None]:
|
63
|
+
"""
|
64
|
+
Return the `id` for the pipe if it exists.
|
65
|
+
|
66
|
+
Parameters
|
67
|
+
----------
|
68
|
+
pipe: mrsm.Pipe
|
69
|
+
The pipe whose `id` to fetch.
|
70
|
+
|
71
|
+
Returns
|
72
|
+
-------
|
73
|
+
The `id` for the pipe's document or `None`.
|
74
|
+
"""
|
75
|
+
|
76
|
+
def edit_pipe(
|
77
|
+
self,
|
78
|
+
pipe: mrsm.Pipe,
|
79
|
+
debug: bool = False,
|
80
|
+
**kwargs: Any
|
81
|
+
) -> mrsm.SuccessTuple:
|
82
|
+
"""
|
83
|
+
Edit the attributes of the pipe.
|
84
|
+
|
85
|
+
Parameters
|
86
|
+
----------
|
87
|
+
pipe: mrsm.Pipe
|
88
|
+
The pipe whose in-memory parameters must be persisted.
|
89
|
+
|
90
|
+
Returns
|
91
|
+
-------
|
92
|
+
A `SuccessTuple` indicating success.
|
93
|
+
"""
|
94
|
+
raise NotImplementedError
|
95
|
+
|
96
|
+
def delete_pipe(
|
97
|
+
self,
|
98
|
+
pipe: mrsm.Pipe,
|
99
|
+
debug: bool = False,
|
100
|
+
**kwargs: Any
|
101
|
+
) -> mrsm.SuccessTuple:
|
102
|
+
"""
|
103
|
+
Delete a pipe's registration from the `pipes` collection.
|
104
|
+
|
105
|
+
Parameters
|
106
|
+
----------
|
107
|
+
pipe: mrsm.Pipe
|
108
|
+
The pipe to be deleted.
|
109
|
+
|
110
|
+
Returns
|
111
|
+
-------
|
112
|
+
A `SuccessTuple` indicating success.
|
113
|
+
"""
|
114
|
+
raise NotImplementedError
|
115
|
+
|
116
|
+
@abc.abstractmethod
|
117
|
+
def fetch_pipes_keys(
|
118
|
+
self,
|
119
|
+
connector_keys: Optional[List[str]] = None,
|
120
|
+
metric_keys: Optional[List[str]] = None,
|
121
|
+
location_keys: Optional[List[str]] = None,
|
122
|
+
tags: Optional[List[str]] = None,
|
123
|
+
debug: bool = False,
|
124
|
+
**kwargs: Any
|
125
|
+
) -> List[Tuple[str, str, str]]:
|
126
|
+
"""
|
127
|
+
Return a list of tuples for the registered pipes' keys according to the provided filters.
|
128
|
+
|
129
|
+
Parameters
|
130
|
+
----------
|
131
|
+
connector_keys: list[str] | None, default None
|
132
|
+
The keys passed via `-c`.
|
133
|
+
|
134
|
+
metric_keys: list[str] | None, default None
|
135
|
+
The keys passed via `-m`.
|
136
|
+
|
137
|
+
location_keys: list[str] | None, default None
|
138
|
+
The keys passed via `-l`.
|
139
|
+
|
140
|
+
tags: List[str] | None, default None
|
141
|
+
Tags passed via `--tags` which are stored under `parameters:tags`.
|
142
|
+
|
143
|
+
Returns
|
144
|
+
-------
|
145
|
+
A list of connector, metric, and location keys in tuples.
|
146
|
+
You may return the string "None" for location keys in place of nulls.
|
147
|
+
|
148
|
+
Examples
|
149
|
+
--------
|
150
|
+
>>> import meerschaum as mrsm
|
151
|
+
>>> conn = mrsm.get_connector('example:demo')
|
152
|
+
>>>
|
153
|
+
>>> pipe_a = mrsm.Pipe('a', 'demo', tags=['foo'], instance=conn)
|
154
|
+
>>> pipe_b = mrsm.Pipe('b', 'demo', tags=['bar'], instance=conn)
|
155
|
+
>>> pipe_a.register()
|
156
|
+
>>> pipe_b.register()
|
157
|
+
>>>
|
158
|
+
>>> conn.fetch_pipes_keys(['a', 'b'])
|
159
|
+
[('a', 'demo', 'None'), ('b', 'demo', 'None')]
|
160
|
+
>>> conn.fetch_pipes_keys(metric_keys=['demo'])
|
161
|
+
[('a', 'demo', 'None'), ('b', 'demo', 'None')]
|
162
|
+
>>> conn.fetch_pipes_keys(tags=['foo'])
|
163
|
+
[('a', 'demo', 'None')]
|
164
|
+
>>> conn.fetch_pipes_keys(location_keys=[None])
|
165
|
+
[('a', 'demo', 'None'), ('b', 'demo', 'None')]
|
166
|
+
"""
|
167
|
+
|
168
|
+
@abc.abstractmethod
|
169
|
+
def pipe_exists(
|
170
|
+
self,
|
171
|
+
pipe: mrsm.Pipe,
|
172
|
+
debug: bool = False,
|
173
|
+
**kwargs: Any
|
174
|
+
) -> bool:
|
175
|
+
"""
|
176
|
+
Check whether a pipe's target table exists.
|
177
|
+
|
178
|
+
Parameters
|
179
|
+
----------
|
180
|
+
pipe: mrsm.Pipe
|
181
|
+
The pipe to check whether its table exists.
|
182
|
+
|
183
|
+
Returns
|
184
|
+
-------
|
185
|
+
A `bool` indicating the table exists.
|
186
|
+
"""
|
187
|
+
|
188
|
+
@abc.abstractmethod
|
189
|
+
def drop_pipe(
|
190
|
+
self,
|
191
|
+
pipe: mrsm.Pipe,
|
192
|
+
debug: bool = False,
|
193
|
+
**kwargs: Any
|
194
|
+
) -> mrsm.SuccessTuple:
|
195
|
+
"""
|
196
|
+
Drop a pipe's collection if it exists.
|
197
|
+
|
198
|
+
Parameters
|
199
|
+
----------
|
200
|
+
pipe: mrsm.Pipe
|
201
|
+
The pipe to be dropped.
|
202
|
+
|
203
|
+
Returns
|
204
|
+
-------
|
205
|
+
A `SuccessTuple` indicating success.
|
206
|
+
"""
|
207
|
+
raise NotImplementedError
|
208
|
+
|
209
|
+
def drop_pipe_indices(
|
210
|
+
self,
|
211
|
+
pipe: mrsm.Pipe,
|
212
|
+
debug: bool = False,
|
213
|
+
**kwargs: Any
|
214
|
+
) -> mrsm.SuccessTuple:
|
215
|
+
"""
|
216
|
+
Drop a pipe's indices.
|
217
|
+
|
218
|
+
Parameters
|
219
|
+
----------
|
220
|
+
pipe: mrsm.Pipe
|
221
|
+
The pipe whose indices need to be dropped.
|
222
|
+
|
223
|
+
Returns
|
224
|
+
-------
|
225
|
+
A `SuccessTuple` indicating success.
|
226
|
+
"""
|
227
|
+
return False, f"Cannot drop indices for instance connectors of type '{self.type}'."
|
228
|
+
|
229
|
+
@abc.abstractmethod
|
230
|
+
def sync_pipe(
|
231
|
+
self,
|
232
|
+
pipe: mrsm.Pipe,
|
233
|
+
df: 'pd.DataFrame' = None,
|
234
|
+
begin: Union[datetime, int, None] = None,
|
235
|
+
end: Union[datetime, int, None] = None,
|
236
|
+
chunksize: Optional[int] = -1,
|
237
|
+
check_existing: bool = True,
|
238
|
+
debug: bool = False,
|
239
|
+
**kwargs: Any
|
240
|
+
) -> mrsm.SuccessTuple:
|
241
|
+
"""
|
242
|
+
Sync a pipe using a database connection.
|
243
|
+
|
244
|
+
Parameters
|
245
|
+
----------
|
246
|
+
pipe: mrsm.Pipe
|
247
|
+
The Meerschaum Pipe instance into which to sync the data.
|
248
|
+
|
249
|
+
df: Optional[pd.DataFrame]
|
250
|
+
An optional DataFrame or equivalent to sync into the pipe.
|
251
|
+
Defaults to `None`.
|
252
|
+
|
253
|
+
begin: Union[datetime, int, None], default None
|
254
|
+
Optionally specify the earliest datetime to search for data.
|
255
|
+
Defaults to `None`.
|
256
|
+
|
257
|
+
end: Union[datetime, int, None], default None
|
258
|
+
Optionally specify the latest datetime to search for data.
|
259
|
+
Defaults to `None`.
|
260
|
+
|
261
|
+
chunksize: Optional[int], default -1
|
262
|
+
Specify the number of rows to sync per chunk.
|
263
|
+
If `-1`, resort to system configuration (default is `900`).
|
264
|
+
A `chunksize` of `None` will sync all rows in one transaction.
|
265
|
+
Defaults to `-1`.
|
266
|
+
|
267
|
+
check_existing: bool, default True
|
268
|
+
If `True`, pull and diff with existing data from the pipe. Defaults to `True`.
|
269
|
+
|
270
|
+
debug: bool, default False
|
271
|
+
Verbosity toggle. Defaults to False.
|
272
|
+
|
273
|
+
Returns
|
274
|
+
-------
|
275
|
+
A `SuccessTuple` of success (`bool`) and message (`str`).
|
276
|
+
"""
|
277
|
+
|
278
|
+
def create_pipe_indices(
|
279
|
+
self,
|
280
|
+
pipe: mrsm.Pipe,
|
281
|
+
debug: bool = False,
|
282
|
+
**kwargs: Any
|
283
|
+
) -> mrsm.SuccessTuple:
|
284
|
+
"""
|
285
|
+
Create a pipe's indices.
|
286
|
+
|
287
|
+
Parameters
|
288
|
+
----------
|
289
|
+
pipe: mrsm.Pipe
|
290
|
+
The pipe whose indices need to be created.
|
291
|
+
|
292
|
+
Returns
|
293
|
+
-------
|
294
|
+
A `SuccessTuple` indicating success.
|
295
|
+
"""
|
296
|
+
return False, f"Cannot create indices for instance connectors of type '{self.type}'."
|
297
|
+
|
298
|
+
def clear_pipe(
|
299
|
+
self,
|
300
|
+
pipe: mrsm.Pipe,
|
301
|
+
begin: Union[datetime, int, None] = None,
|
302
|
+
end: Union[datetime, int, None] = None,
|
303
|
+
params: Optional[Dict[str, Any]] = None,
|
304
|
+
debug: bool = False,
|
305
|
+
**kwargs: Any
|
306
|
+
) -> mrsm.SuccessTuple:
|
307
|
+
"""
|
308
|
+
Delete rows within `begin`, `end`, and `params`.
|
309
|
+
|
310
|
+
Parameters
|
311
|
+
----------
|
312
|
+
pipe: mrsm.Pipe
|
313
|
+
The pipe whose rows to clear.
|
314
|
+
|
315
|
+
begin: datetime | int | None, default None
|
316
|
+
If provided, remove rows >= `begin`.
|
317
|
+
|
318
|
+
end: datetime | int | None, default None
|
319
|
+
If provided, remove rows < `end`.
|
320
|
+
|
321
|
+
params: dict[str, Any] | None, default None
|
322
|
+
If provided, only remove rows which match the `params` filter.
|
323
|
+
|
324
|
+
Returns
|
325
|
+
-------
|
326
|
+
A `SuccessTuple` indicating success.
|
327
|
+
"""
|
328
|
+
raise NotImplementedError
|
329
|
+
|
330
|
+
@abc.abstractmethod
|
331
|
+
def get_pipe_data(
|
332
|
+
self,
|
333
|
+
pipe: mrsm.Pipe,
|
334
|
+
select_columns: Optional[List[str]] = None,
|
335
|
+
omit_columns: Optional[List[str]] = None,
|
336
|
+
begin: Union[datetime, int, None] = None,
|
337
|
+
end: Union[datetime, int, None] = None,
|
338
|
+
params: Optional[Dict[str, Any]] = None,
|
339
|
+
debug: bool = False,
|
340
|
+
**kwargs: Any
|
341
|
+
) -> Union['pd.DataFrame', None]:
|
342
|
+
"""
|
343
|
+
Query a pipe's target table and return the DataFrame.
|
344
|
+
|
345
|
+
Parameters
|
346
|
+
----------
|
347
|
+
pipe: mrsm.Pipe
|
348
|
+
The pipe with the target table from which to read.
|
349
|
+
|
350
|
+
select_columns: list[str] | None, default None
|
351
|
+
If provided, only select these given columns.
|
352
|
+
Otherwise select all available columns (i.e. `SELECT *`).
|
353
|
+
|
354
|
+
omit_columns: list[str] | None, default None
|
355
|
+
If provided, remove these columns from the selection.
|
356
|
+
|
357
|
+
begin: datetime | int | None, default None
|
358
|
+
The earliest `datetime` value to search from (inclusive).
|
359
|
+
|
360
|
+
end: datetime | int | None, default None
|
361
|
+
The lastest `datetime` value to search from (exclusive).
|
362
|
+
|
363
|
+
params: dict[str | str] | None, default None
|
364
|
+
Additional filters to apply to the query.
|
365
|
+
|
366
|
+
Returns
|
367
|
+
-------
|
368
|
+
The target table's data as a DataFrame.
|
369
|
+
"""
|
370
|
+
|
371
|
+
@abc.abstractmethod
|
372
|
+
def get_sync_time(
|
373
|
+
self,
|
374
|
+
pipe: mrsm.Pipe,
|
375
|
+
params: Optional[Dict[str, Any]] = None,
|
376
|
+
newest: bool = True,
|
377
|
+
debug: bool = False,
|
378
|
+
**kwargs: Any
|
379
|
+
) -> datetime | int | None:
|
380
|
+
"""
|
381
|
+
Return the most recent value for the `datetime` axis.
|
382
|
+
|
383
|
+
Parameters
|
384
|
+
----------
|
385
|
+
pipe: mrsm.Pipe
|
386
|
+
The pipe whose collection contains documents.
|
387
|
+
|
388
|
+
params: dict[str, Any] | None, default None
|
389
|
+
Filter certain parameters when determining the sync time.
|
390
|
+
|
391
|
+
newest: bool, default True
|
392
|
+
If `True`, return the maximum value for the column.
|
393
|
+
|
394
|
+
Returns
|
395
|
+
-------
|
396
|
+
The largest `datetime` or `int` value of the `datetime` axis.
|
397
|
+
"""
|
398
|
+
|
399
|
+
@abc.abstractmethod
|
400
|
+
def get_pipe_columns_types(
|
401
|
+
self,
|
402
|
+
pipe: mrsm.Pipe,
|
403
|
+
debug: bool = False,
|
404
|
+
**kwargs: Any
|
405
|
+
) -> Dict[str, str]:
|
406
|
+
"""
|
407
|
+
Return the data types for the columns in the target table for data type enforcement.
|
408
|
+
|
409
|
+
Parameters
|
410
|
+
----------
|
411
|
+
pipe: mrsm.Pipe
|
412
|
+
The pipe whose target table contains columns and data types.
|
413
|
+
|
414
|
+
Returns
|
415
|
+
-------
|
416
|
+
A dictionary mapping columns to data types.
|
417
|
+
"""
|
418
|
+
|
419
|
+
def get_pipe_columns_indices(
|
420
|
+
self,
|
421
|
+
debug: bool = False,
|
422
|
+
) -> Dict[str, List[Dict[str, str]]]:
|
423
|
+
"""
|
424
|
+
Return a dictionary mapping columns to metadata about related indices.
|
425
|
+
|
426
|
+
Parameters
|
427
|
+
----------
|
428
|
+
pipe: mrsm.Pipe
|
429
|
+
The pipe whose target table has related indices.
|
430
|
+
|
431
|
+
Returns
|
432
|
+
-------
|
433
|
+
A list of dictionaries with the keys "type" and "name".
|
434
|
+
|
435
|
+
Examples
|
436
|
+
--------
|
437
|
+
>>> pipe = mrsm.Pipe('demo', 'shirts', columns={'primary': 'id'}, indices={'size_color': ['color', 'size']})
|
438
|
+
>>> pipe.sync([{'color': 'red', 'size': 'M'}])
|
439
|
+
>>> pipe.get_columns_indices()
|
440
|
+
{'id': [{'name': 'demo_shirts_pkey', 'type': 'PRIMARY KEY'}], 'color': [{'name': 'IX_demo_shirts_color_size', 'type': 'INDEX'}], 'size': [{'name': 'IX_demo_shirts_color_size', 'type': 'INDEX'}]}
|
441
|
+
"""
|
442
|
+
return {}
|
@@ -0,0 +1,159 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define high-level plugins methods for instance connectors.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import uuid
|
9
|
+
from typing import Union, Optional, List, Dict, Any
|
10
|
+
|
11
|
+
import meerschaum as mrsm
|
12
|
+
from meerschaum.core import Plugin
|
13
|
+
|
14
|
+
|
15
|
+
def get_plugins_pipe(self) -> 'mrsm.Pipe':
|
16
|
+
"""
|
17
|
+
Return the internal pipe for syncing plugins metadata.
|
18
|
+
"""
|
19
|
+
if '_plugins_pipe' in self.__dict__:
|
20
|
+
return self._plugins_pipe
|
21
|
+
|
22
|
+
cache_connector = self.__dict__.get('_cache_connector', None)
|
23
|
+
users_pipe = self.get_users_pipe()
|
24
|
+
user_id_dtype = users_pipe.dtypes.get('user_id', 'uuid')
|
25
|
+
|
26
|
+
self._plugins_pipe = mrsm.Pipe(
|
27
|
+
'mrsm', 'plugins',
|
28
|
+
instance=self,
|
29
|
+
target='mrsm_plugins',
|
30
|
+
temporary=True,
|
31
|
+
cache=True,
|
32
|
+
cache_connector_keys=cache_connector,
|
33
|
+
static=True,
|
34
|
+
null_indices=False,
|
35
|
+
columns={
|
36
|
+
'primary': 'plugin_name',
|
37
|
+
'user_id': 'user_id',
|
38
|
+
},
|
39
|
+
dtypes={
|
40
|
+
'plugin_name': 'string',
|
41
|
+
'user_id': user_id_dtype,
|
42
|
+
'attributes': 'json',
|
43
|
+
'version': 'string',
|
44
|
+
},
|
45
|
+
)
|
46
|
+
return self._plugins_pipe
|
47
|
+
|
48
|
+
|
49
|
+
def register_plugin(self, plugin: Plugin, debug: bool = False) -> mrsm.SuccessTuple:
|
50
|
+
"""
|
51
|
+
Register a new plugin to the plugins table.
|
52
|
+
"""
|
53
|
+
plugins_pipe = self.get_plugins_pipe()
|
54
|
+
users_pipe = self.get_users_pipe()
|
55
|
+
user_id = self.get_plugin_user_id(plugin)
|
56
|
+
if user_id is not None:
|
57
|
+
username = self.get_username(user_id, debug=debug)
|
58
|
+
return False, f"{plugin} is already registered to '{username}'."
|
59
|
+
|
60
|
+
doc = {
|
61
|
+
'plugin_name': plugin.name,
|
62
|
+
'version': plugin.version,
|
63
|
+
'attributes': plugin.attributes,
|
64
|
+
'user_id': plugin.user_id,
|
65
|
+
}
|
66
|
+
|
67
|
+
sync_success, sync_msg = plugins_pipe.sync(
|
68
|
+
[doc],
|
69
|
+
check_existing=False,
|
70
|
+
debug=debug,
|
71
|
+
)
|
72
|
+
if not sync_success:
|
73
|
+
return False, f"Failed to register {plugin}:\n{sync_msg}"
|
74
|
+
|
75
|
+
return True, "Success"
|
76
|
+
|
77
|
+
|
78
|
+
def get_plugin_user_id(self, plugin: Plugin, debug: bool = False) -> Union[uuid.UUID, None]:
|
79
|
+
"""
|
80
|
+
Return the user ID for plugin's owner.
|
81
|
+
"""
|
82
|
+
plugins_pipe = self.get_plugins_pipe()
|
83
|
+
return plugins_pipe.get_value('user_id', {'plugin_name': plugin.name}, debug=debug)
|
84
|
+
|
85
|
+
|
86
|
+
def get_plugin_username(self, plugin: Plugin, debug: bool = False) -> Union[uuid.UUID, None]:
|
87
|
+
"""
|
88
|
+
Return the username for plugin's owner.
|
89
|
+
"""
|
90
|
+
user_id = self.get_plugin_user_id(plugin, debug=debug)
|
91
|
+
if user_id is None:
|
92
|
+
return None
|
93
|
+
return self.get_username(user_id, debug=debug)
|
94
|
+
|
95
|
+
|
96
|
+
def get_plugin_id(self, plugin: Plugin, debug: bool = False) -> Union[str, None]:
|
97
|
+
"""
|
98
|
+
Return a plugin's ID.
|
99
|
+
"""
|
100
|
+
user_id = self.get_plugin_user_id(plugin, debug=debug)
|
101
|
+
return plugin.name if user_id is not None else None
|
102
|
+
|
103
|
+
|
104
|
+
def delete_plugin(self, plugin: Plugin, debug: bool = False) -> mrsm.SuccessTuple:
|
105
|
+
"""
|
106
|
+
Delete a plugin's registration.
|
107
|
+
"""
|
108
|
+
plugin_id = self.get_plugin_id(plugin, debug=debug)
|
109
|
+
if plugin_id is None:
|
110
|
+
return False, f"{plugin} is not registered."
|
111
|
+
|
112
|
+
plugins_pipe = self.get_plugins_pipe()
|
113
|
+
clear_success, clear_msg = plugins_pipe.clear(params={'plugin_name': plugin.name}, debug=debug)
|
114
|
+
if not clear_success:
|
115
|
+
return False, f"Failed to delete {plugin}:\n{clear_msg}"
|
116
|
+
return True, "Success"
|
117
|
+
|
118
|
+
|
119
|
+
def get_plugin_version(self, plugin: Plugin, debug: bool = False) -> Union[str, None]:
|
120
|
+
"""
|
121
|
+
Return the version for a plugin.
|
122
|
+
"""
|
123
|
+
plugins_pipe = self.get_plugins_pipe()
|
124
|
+
return plugins_pipe.get_value('version', {'plugin_name': plugin.name}, debug=debug)
|
125
|
+
|
126
|
+
|
127
|
+
def get_plugin_attributes(self, plugin: Plugin, debug: bool = False) -> Dict[str, Any]:
|
128
|
+
"""
|
129
|
+
Return the attributes for a plugin.
|
130
|
+
"""
|
131
|
+
plugins_pipe = self.get_plugins_pipe()
|
132
|
+
return plugins_pipe.get_value('attributes', {'plugin_name': plugin.name}, debug=debug) or {}
|
133
|
+
|
134
|
+
|
135
|
+
def get_plugins(
|
136
|
+
self,
|
137
|
+
user_id: Optional[int] = None,
|
138
|
+
search_term: Optional[str] = None,
|
139
|
+
debug: bool = False,
|
140
|
+
**kw: Any
|
141
|
+
) -> List[str]:
|
142
|
+
"""
|
143
|
+
Return a list of plugin names.
|
144
|
+
"""
|
145
|
+
plugins_pipe = self.get_plugins_pipe()
|
146
|
+
params = {}
|
147
|
+
if user_id:
|
148
|
+
params['user_id'] = user_id
|
149
|
+
|
150
|
+
df = plugins_pipe.get_data(['plugin_name'], params=params, debug=debug)
|
151
|
+
if df is None:
|
152
|
+
return []
|
153
|
+
|
154
|
+
docs = df.to_dict(orient='records')
|
155
|
+
return [
|
156
|
+
plugin_name
|
157
|
+
for doc in docs
|
158
|
+
if (plugin_name := doc['plugin_name']).startswith(search_term or '')
|
159
|
+
]
|