meerschaum 2.2.0rc4__py3-none-any.whl → 2.2.2__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/_internal/entry.py +36 -11
- meerschaum/_internal/shell/Shell.py +40 -16
- meerschaum/_internal/term/__init__.py +3 -2
- meerschaum/_internal/term/tools.py +1 -1
- meerschaum/actions/api.py +65 -31
- meerschaum/actions/python.py +56 -24
- meerschaum/actions/start.py +2 -4
- meerschaum/actions/uninstall.py +5 -9
- meerschaum/actions/upgrade.py +11 -3
- meerschaum/api/__init__.py +1 -0
- meerschaum/api/dash/callbacks/__init__.py +4 -0
- meerschaum/api/dash/callbacks/custom.py +39 -0
- meerschaum/api/dash/callbacks/dashboard.py +39 -6
- meerschaum/api/dash/callbacks/login.py +3 -1
- meerschaum/api/dash/components.py +5 -2
- meerschaum/api/dash/pipes.py +145 -97
- meerschaum/config/_default.py +1 -0
- meerschaum/config/_paths.py +12 -12
- meerschaum/config/_version.py +1 -1
- meerschaum/config/paths.py +10 -0
- meerschaum/config/static/__init__.py +1 -1
- meerschaum/connectors/__init__.py +9 -2
- meerschaum/connectors/sql/_cli.py +7 -1
- meerschaum/connectors/sql/_pipes.py +6 -0
- meerschaum/core/Pipe/__init__.py +5 -0
- meerschaum/core/Pipe/_sync.py +2 -3
- meerschaum/plugins/__init__.py +67 -9
- meerschaum/utils/daemon/Daemon.py +7 -2
- meerschaum/utils/misc.py +6 -0
- meerschaum/utils/packages/__init__.py +212 -53
- meerschaum/utils/packages/_packages.py +3 -2
- meerschaum/utils/process.py +12 -2
- meerschaum/utils/schedule.py +10 -3
- meerschaum/utils/venv/__init__.py +46 -11
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/METADATA +13 -9
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/RECORD +42 -40
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/WHEEL +1 -1
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/LICENSE +0 -0
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/NOTICE +0 -0
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/top_level.txt +0 -0
- {meerschaum-2.2.0rc4.dist-info → meerschaum-2.2.2.dist-info}/zip-safe +0 -0
@@ -94,6 +94,8 @@ omit_actions = {
|
|
94
94
|
'repo',
|
95
95
|
'instance',
|
96
96
|
}
|
97
|
+
|
98
|
+
### Map endpoints to page layouts.
|
97
99
|
_paths = {
|
98
100
|
'login' : pages.login.layout,
|
99
101
|
'' : pages.dashboard.layout,
|
@@ -101,7 +103,8 @@ _paths = {
|
|
101
103
|
'register': pages.register.layout,
|
102
104
|
}
|
103
105
|
_required_login = {''}
|
104
|
-
|
106
|
+
|
107
|
+
|
105
108
|
@dash_app.callback(
|
106
109
|
Output('page-layout-div', 'children'),
|
107
110
|
Output('session-store', 'data'),
|
@@ -147,16 +150,31 @@ def update_page_layout_div(
|
|
147
150
|
else:
|
148
151
|
session_store_to_return = dash.no_update
|
149
152
|
|
150
|
-
|
153
|
+
base_path = (
|
151
154
|
pathname.rstrip('/') + '/'
|
152
155
|
).replace(
|
153
156
|
(dash_endpoint + '/'),
|
154
157
|
''
|
155
158
|
).rstrip('/').split('/')[0]
|
159
|
+
|
160
|
+
complete_path = (
|
161
|
+
pathname.rstrip('/') + '/'
|
162
|
+
).replace(
|
163
|
+
dash_endpoint + '/',
|
164
|
+
''
|
165
|
+
).rstrip('/')
|
166
|
+
|
167
|
+
if complete_path in _paths:
|
168
|
+
path_str = complete_path
|
169
|
+
elif base_path in _paths:
|
170
|
+
path_str = base_path
|
171
|
+
else:
|
172
|
+
path_str = ''
|
173
|
+
|
156
174
|
path = (
|
157
|
-
|
158
|
-
if no_auth or
|
159
|
-
|
175
|
+
path_str
|
176
|
+
if no_auth or path_str not in _required_login else (
|
177
|
+
path_str
|
160
178
|
if session_id in active_sessions
|
161
179
|
else 'login'
|
162
180
|
)
|
@@ -868,10 +886,25 @@ dash_app.clientside_callback(
|
|
868
886
|
location = "None";
|
869
887
|
}
|
870
888
|
|
889
|
+
var subaction = "pipes";
|
890
|
+
if (action == "python"){
|
891
|
+
subaction = (
|
892
|
+
'"' + "pipe = mrsm.Pipe('"
|
893
|
+
+ pipe_meta.connector
|
894
|
+
+ "', '"
|
895
|
+
+ pipe_meta.metric
|
896
|
+
+ "'"
|
897
|
+
);
|
898
|
+
if (location != "None"){
|
899
|
+
subaction += ", '" + location + "'";
|
900
|
+
}
|
901
|
+
subaction += ", instance='" + pipe_meta.instance + "')" + '"';
|
902
|
+
}
|
903
|
+
|
871
904
|
iframe.contentWindow.postMessage(
|
872
905
|
{
|
873
906
|
action: action,
|
874
|
-
subaction:
|
907
|
+
subaction: subaction,
|
875
908
|
connector_keys: [pipe_meta.connector],
|
876
909
|
metric_keys: [pipe_meta.metric],
|
877
910
|
location_keys: [location],
|
@@ -45,6 +45,7 @@ def show_registration_disabled_collapse(n_clicks, is_open):
|
|
45
45
|
State('username-input', 'value'),
|
46
46
|
State('password-input', 'value'),
|
47
47
|
State('location', 'href'),
|
48
|
+
State('location', 'pathname'),
|
48
49
|
)
|
49
50
|
def login_button_click(
|
50
51
|
username_submit,
|
@@ -53,6 +54,7 @@ def login_button_click(
|
|
53
54
|
username,
|
54
55
|
password,
|
55
56
|
location_href,
|
57
|
+
location_pathname,
|
56
58
|
):
|
57
59
|
"""
|
58
60
|
When the user submits the login form, check the login.
|
@@ -69,4 +71,4 @@ def login_button_click(
|
|
69
71
|
except HTTPException:
|
70
72
|
form_class += ' is-invalid'
|
71
73
|
session_data = None
|
72
|
-
return session_data, form_class,
|
74
|
+
return session_data, form_class, dash.no_update
|
@@ -12,7 +12,7 @@ from meerschaum.utils.packages import attempt_import, import_dcc, import_html
|
|
12
12
|
from meerschaum.utils.typing import SuccessTuple, List
|
13
13
|
from meerschaum.config.static import STATIC_CONFIG
|
14
14
|
from meerschaum.utils.misc import remove_ansi
|
15
|
-
from meerschaum.
|
15
|
+
from meerschaum._internal.shell.Shell import get_shell_intro
|
16
16
|
from meerschaum.api import endpoints, CHECK_UPDATE
|
17
17
|
from meerschaum.connectors import instance_types
|
18
18
|
from meerschaum.utils.misc import get_connector_labels
|
@@ -69,7 +69,10 @@ bottom_buttons_content = dbc.Card(
|
|
69
69
|
])
|
70
70
|
)
|
71
71
|
)
|
72
|
-
console_div = html.Div(
|
72
|
+
console_div = html.Div(
|
73
|
+
id = 'console-div',
|
74
|
+
children = [html.Pre(get_shell_intro(), id='console-pre')],
|
75
|
+
)
|
73
76
|
|
74
77
|
location = dcc.Location(id='location', refresh=False)
|
75
78
|
|
meerschaum/api/dash/pipes.py
CHANGED
@@ -22,7 +22,7 @@ from meerschaum.api.dash import (
|
|
22
22
|
dash_app, debug, _get_pipes
|
23
23
|
)
|
24
24
|
from meerschaum.api.dash.connectors import get_web_connector
|
25
|
-
from meerschaum.api.dash.components import alert_from_success_tuple
|
25
|
+
from meerschaum.api.dash.components import alert_from_success_tuple, build_cards_grid
|
26
26
|
from meerschaum.api.dash.users import is_session_authenticated
|
27
27
|
from meerschaum.config import get_config
|
28
28
|
import meerschaum as mrsm
|
@@ -101,6 +101,132 @@ def pipes_from_state(
|
|
101
101
|
return False, str(e)
|
102
102
|
return _pipes
|
103
103
|
|
104
|
+
|
105
|
+
def build_pipe_card(
|
106
|
+
pipe: mrsm.Pipe,
|
107
|
+
authenticated: bool = False,
|
108
|
+
_build_children_num: int = 10,
|
109
|
+
) -> 'dbc.Card':
|
110
|
+
"""
|
111
|
+
Return a card for the given pipe.
|
112
|
+
|
113
|
+
Parameters
|
114
|
+
----------
|
115
|
+
pipe: mrsm.Pipe
|
116
|
+
The pipe from which to build the card.
|
117
|
+
|
118
|
+
authenticated: bool, default False
|
119
|
+
If `True`, allow editing functionality to the card.
|
120
|
+
|
121
|
+
Returns
|
122
|
+
-------
|
123
|
+
A dash bootstrap components Card representation of the pipe.
|
124
|
+
"""
|
125
|
+
meta_str = json.dumps(pipe.meta)
|
126
|
+
footer_children = dbc.Row(
|
127
|
+
[
|
128
|
+
dbc.Col(
|
129
|
+
(
|
130
|
+
dbc.DropdownMenu(
|
131
|
+
label = "Manage",
|
132
|
+
children = [
|
133
|
+
dbc.DropdownMenuItem(
|
134
|
+
'Open in Python',
|
135
|
+
id = {
|
136
|
+
'type': 'manage-pipe-button',
|
137
|
+
'index': meta_str,
|
138
|
+
'action': 'python',
|
139
|
+
},
|
140
|
+
),
|
141
|
+
dbc.DropdownMenuItem(
|
142
|
+
'Delete',
|
143
|
+
id = {
|
144
|
+
'type': 'manage-pipe-button',
|
145
|
+
'index': meta_str,
|
146
|
+
'action': 'delete',
|
147
|
+
},
|
148
|
+
),
|
149
|
+
dbc.DropdownMenuItem(
|
150
|
+
'Drop',
|
151
|
+
id = {
|
152
|
+
'type': 'manage-pipe-button',
|
153
|
+
'index': meta_str,
|
154
|
+
'action': 'drop',
|
155
|
+
},
|
156
|
+
),
|
157
|
+
dbc.DropdownMenuItem(
|
158
|
+
'Clear',
|
159
|
+
id = {
|
160
|
+
'type': 'manage-pipe-button',
|
161
|
+
'index': meta_str,
|
162
|
+
'action': 'clear',
|
163
|
+
},
|
164
|
+
),
|
165
|
+
dbc.DropdownMenuItem(
|
166
|
+
'Verify',
|
167
|
+
id = {
|
168
|
+
'type': 'manage-pipe-button',
|
169
|
+
'index': meta_str,
|
170
|
+
'action': 'verify',
|
171
|
+
},
|
172
|
+
),
|
173
|
+
dbc.DropdownMenuItem(
|
174
|
+
'Sync',
|
175
|
+
id = {
|
176
|
+
'type': 'manage-pipe-button',
|
177
|
+
'index': meta_str,
|
178
|
+
'action': 'sync',
|
179
|
+
},
|
180
|
+
),
|
181
|
+
],
|
182
|
+
direction = "up",
|
183
|
+
menu_variant = "dark",
|
184
|
+
size = 'sm',
|
185
|
+
color = 'secondary',
|
186
|
+
)
|
187
|
+
) if authenticated else [],
|
188
|
+
width = 2,
|
189
|
+
),
|
190
|
+
dbc.Col(width=6),
|
191
|
+
dbc.Col(
|
192
|
+
dbc.Button(
|
193
|
+
'Download CSV',
|
194
|
+
size = 'sm',
|
195
|
+
color = 'link',
|
196
|
+
style = {'float': 'right'},
|
197
|
+
id = {'type': 'pipe-download-csv-button', 'index': meta_str},
|
198
|
+
),
|
199
|
+
width = 4,
|
200
|
+
),
|
201
|
+
],
|
202
|
+
justify = 'start',
|
203
|
+
)
|
204
|
+
card_body_children = [
|
205
|
+
html.H5(
|
206
|
+
html.B(str(pipe)),
|
207
|
+
className = 'card-title',
|
208
|
+
style = {'font-family': ['monospace']}
|
209
|
+
),
|
210
|
+
html.Div(
|
211
|
+
dbc.Accordion(
|
212
|
+
accordion_items_from_pipe(
|
213
|
+
pipe,
|
214
|
+
authenticated = authenticated,
|
215
|
+
_build_children_num = _build_children_num,
|
216
|
+
),
|
217
|
+
flush = True,
|
218
|
+
start_collapsed = True,
|
219
|
+
id = {'type': 'pipe-accordion', 'index': meta_str},
|
220
|
+
)
|
221
|
+
)
|
222
|
+
|
223
|
+
]
|
224
|
+
return dbc.Card([
|
225
|
+
dbc.CardBody(children=card_body_children),
|
226
|
+
dbc.CardFooter(children=footer_children),
|
227
|
+
])
|
228
|
+
|
229
|
+
|
104
230
|
def get_pipes_cards(*keys, session_data: Optional[Dict[str, Any]] = None):
|
105
231
|
"""
|
106
232
|
Returns a tuple:
|
@@ -120,99 +246,7 @@ def get_pipes_cards(*keys, session_data: Optional[Dict[str, Any]] = None):
|
|
120
246
|
overflow_pipes = pipes[max_num_pipes_cards:]
|
121
247
|
|
122
248
|
for pipe in pipes[:max_num_pipes_cards]:
|
123
|
-
|
124
|
-
footer_children = dbc.Row(
|
125
|
-
[
|
126
|
-
dbc.Col(
|
127
|
-
(
|
128
|
-
dbc.DropdownMenu(
|
129
|
-
label = "Manage",
|
130
|
-
children = [
|
131
|
-
dbc.DropdownMenuItem(
|
132
|
-
'Delete',
|
133
|
-
id = {
|
134
|
-
'type': 'manage-pipe-button',
|
135
|
-
'index': meta_str,
|
136
|
-
'action': 'delete',
|
137
|
-
},
|
138
|
-
),
|
139
|
-
dbc.DropdownMenuItem(
|
140
|
-
'Drop',
|
141
|
-
id = {
|
142
|
-
'type': 'manage-pipe-button',
|
143
|
-
'index': meta_str,
|
144
|
-
'action': 'drop',
|
145
|
-
},
|
146
|
-
),
|
147
|
-
dbc.DropdownMenuItem(
|
148
|
-
'Clear',
|
149
|
-
id = {
|
150
|
-
'type': 'manage-pipe-button',
|
151
|
-
'index': meta_str,
|
152
|
-
'action': 'clear',
|
153
|
-
},
|
154
|
-
),
|
155
|
-
dbc.DropdownMenuItem(
|
156
|
-
'Verify',
|
157
|
-
id = {
|
158
|
-
'type': 'manage-pipe-button',
|
159
|
-
'index': meta_str,
|
160
|
-
'action': 'verify',
|
161
|
-
},
|
162
|
-
),
|
163
|
-
dbc.DropdownMenuItem(
|
164
|
-
'Sync',
|
165
|
-
id = {
|
166
|
-
'type': 'manage-pipe-button',
|
167
|
-
'index': meta_str,
|
168
|
-
'action': 'sync',
|
169
|
-
},
|
170
|
-
),
|
171
|
-
],
|
172
|
-
direction = "up",
|
173
|
-
menu_variant = "dark",
|
174
|
-
size = 'sm',
|
175
|
-
color = 'secondary',
|
176
|
-
)
|
177
|
-
) if authenticated else [],
|
178
|
-
width = 2,
|
179
|
-
),
|
180
|
-
dbc.Col(width=6),
|
181
|
-
dbc.Col(
|
182
|
-
dbc.Button(
|
183
|
-
'Download CSV',
|
184
|
-
size = 'sm',
|
185
|
-
color = 'link',
|
186
|
-
style = {'float': 'right'},
|
187
|
-
id = {'type': 'pipe-download-csv-button', 'index': meta_str},
|
188
|
-
),
|
189
|
-
width = 4,
|
190
|
-
),
|
191
|
-
],
|
192
|
-
justify = 'start',
|
193
|
-
)
|
194
|
-
card_body_children = [
|
195
|
-
html.H5(
|
196
|
-
html.B(str(pipe)),
|
197
|
-
className = 'card-title',
|
198
|
-
style = {'font-family': ['monospace']}
|
199
|
-
),
|
200
|
-
html.Div(
|
201
|
-
dbc.Accordion(
|
202
|
-
accordion_items_from_pipe(pipe, authenticated=authenticated),
|
203
|
-
flush = True,
|
204
|
-
start_collapsed = True,
|
205
|
-
id = {'type': 'pipe-accordion', 'index': meta_str},
|
206
|
-
)
|
207
|
-
)
|
208
|
-
|
209
|
-
]
|
210
|
-
cards.append(
|
211
|
-
dbc.Card([
|
212
|
-
dbc.CardBody(children=card_body_children),
|
213
|
-
dbc.CardFooter(children=footer_children),
|
214
|
-
])
|
215
|
-
)
|
249
|
+
cards.append(build_pipe_card(pipe, authenticated=authenticated))
|
216
250
|
|
217
251
|
if overflow_pipes:
|
218
252
|
cards.append(
|
@@ -239,7 +273,8 @@ def accordion_items_from_pipe(
|
|
239
273
|
pipe: mrsm.Pipe,
|
240
274
|
active_items: Optional[List[str]] = None,
|
241
275
|
authenticated: bool = False,
|
242
|
-
|
276
|
+
_build_children_num: int = 10,
|
277
|
+
) -> 'List[dbc.AccordionItem]':
|
243
278
|
"""
|
244
279
|
Build the accordion items for a given pipe.
|
245
280
|
"""
|
@@ -401,7 +436,7 @@ def accordion_items_from_pipe(
|
|
401
436
|
size = 'sm',
|
402
437
|
style = {'text-decoration': 'none', 'margin-left': '10px'},
|
403
438
|
)
|
404
|
-
|
439
|
+
parameters_div_children = [
|
405
440
|
parameters_editor,
|
406
441
|
html.Br(),
|
407
442
|
dbc.Row([
|
@@ -422,8 +457,21 @@ def accordion_items_from_pipe(
|
|
422
457
|
width=True,
|
423
458
|
)
|
424
459
|
]),
|
460
|
+
]
|
461
|
+
if _build_children_num > 0 and pipe.children:
|
462
|
+
children_cards = [
|
463
|
+
build_pipe_card(
|
464
|
+
child_pipe,
|
465
|
+
authenticated = authenticated,
|
466
|
+
_build_children_num = (_build_children_num - 1),
|
467
|
+
)
|
468
|
+
for child_pipe in pipe.children
|
469
|
+
]
|
470
|
+
children_grid = build_cards_grid(children_cards, num_columns=1)
|
471
|
+
chidren_div_items = [html.Br(), html.H3('Children Pipes'), html.Br(), children_grid]
|
472
|
+
parameters_div_children.extend([html.Br()] + chidren_div_items)
|
425
473
|
|
426
|
-
])
|
474
|
+
items_bodies['parameters'] = html.Div(parameters_div_children)
|
427
475
|
|
428
476
|
if 'sql' in active_items:
|
429
477
|
query = dedent((get_pipe_query(pipe, warn=False) or "")).lstrip().rstrip()
|
meerschaum/config/_default.py
CHANGED
meerschaum/config/_paths.py
CHANGED
@@ -82,24 +82,24 @@ for _plugin_path in _plugins_paths_to_remove:
|
|
82
82
|
|
83
83
|
ENVIRONMENT_VENVS_DIR = STATIC_CONFIG['environment']['venvs']
|
84
84
|
if ENVIRONMENT_VENVS_DIR in os.environ:
|
85
|
-
|
86
|
-
if not
|
85
|
+
_VENVS_DIR_PATH = Path(os.environ[ENVIRONMENT_VENVS_DIR]).resolve()
|
86
|
+
if not _VENVS_DIR_PATH.exists():
|
87
87
|
try:
|
88
|
-
|
88
|
+
_VENVS_DIR_PATH.mkdir(parents=True, exist_ok=True)
|
89
89
|
except Exception as e:
|
90
90
|
print(
|
91
91
|
f"Invalid path set for environment variable '{ENVIRONMENT_VENVS_DIR}':\n"
|
92
|
-
+ f"{
|
92
|
+
+ f"{_VENVS_DIR_PATH}"
|
93
93
|
)
|
94
|
-
|
95
|
-
print(f"Will use the following path for venvs instead:\n{
|
94
|
+
_VENVS_DIR_PATH = (_ROOT_DIR_PATH / 'venvs').resolve()
|
95
|
+
print(f"Will use the following path for venvs instead:\n{_VENVS_DIR_PATH}")
|
96
96
|
else:
|
97
|
-
|
97
|
+
_VENVS_DIR_PATH = _ROOT_DIR_PATH / 'venvs'
|
98
98
|
|
99
99
|
paths = {
|
100
|
-
'PACKAGE_ROOT_PATH' :
|
101
|
-
'ROOT_DIR_PATH' :
|
102
|
-
'VIRTENV_RESOURCES_PATH' :
|
100
|
+
'PACKAGE_ROOT_PATH' : Path(__file__).parent.parent.resolve().as_posix(),
|
101
|
+
'ROOT_DIR_PATH' : _ROOT_DIR_PATH.as_posix(),
|
102
|
+
'VIRTENV_RESOURCES_PATH' : _VENVS_DIR_PATH.as_posix(),
|
103
103
|
'CONFIG_DIR_PATH' : ('{ROOT_DIR_PATH}', 'config'),
|
104
104
|
'DEFAULT_CONFIG_DIR_PATH' : ('{ROOT_DIR_PATH}', 'default_config'),
|
105
105
|
'PATCH_DIR_PATH' : ('{ROOT_DIR_PATH}', 'patch_config'),
|
@@ -114,6 +114,7 @@ paths = {
|
|
114
114
|
|
115
115
|
'SHELL_RESOURCES_PATH' : ('{ROOT_DIR_PATH}', ),
|
116
116
|
'SHELL_HISTORY_PATH' : ('{SHELL_RESOURCES_PATH}', '.mrsm_history'),
|
117
|
+
'PYTHON_RESOURCES_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'python'),
|
117
118
|
|
118
119
|
'API_RESOURCES_PATH' : ('{PACKAGE_ROOT_PATH}', 'api', 'resources'),
|
119
120
|
'API_STATIC_PATH' : ('{API_RESOURCES_PATH}', 'static'),
|
@@ -186,7 +187,6 @@ def __getattr__(name: str) -> Path:
|
|
186
187
|
if name.endswith('RESOURCES_PATH') or name == 'CONFIG_DIR_PATH':
|
187
188
|
path.mkdir(parents=True, exist_ok=True)
|
188
189
|
elif 'FILENAME' in name:
|
189
|
-
path =
|
190
|
+
path = path.as_posix()
|
190
191
|
|
191
192
|
return path
|
192
|
-
|
meerschaum/config/_version.py
CHANGED
@@ -110,7 +110,7 @@ STATIC_CONFIG: Dict[str, Any] = {
|
|
110
110
|
'pbkdf2_sha256',
|
111
111
|
],
|
112
112
|
'default': 'pbkdf2_sha256',
|
113
|
-
'pbkdf2_sha256__default_rounds':
|
113
|
+
'pbkdf2_sha256__default_rounds': 1_000_000,
|
114
114
|
},
|
115
115
|
'min_username_length': 1,
|
116
116
|
'max_username_length': 26,
|
@@ -23,7 +23,14 @@ from meerschaum.connectors.sql.SQLConnector import SQLConnector
|
|
23
23
|
from meerschaum.connectors.api.APIConnector import APIConnector
|
24
24
|
from meerschaum.connectors.sql._create_engine import flavor_configs as sql_flavor_configs
|
25
25
|
|
26
|
-
__all__ = (
|
26
|
+
__all__ = (
|
27
|
+
"Connector",
|
28
|
+
"SQLConnector",
|
29
|
+
"APIConnector",
|
30
|
+
"get_connector",
|
31
|
+
"is_connected",
|
32
|
+
"poll",
|
33
|
+
)
|
27
34
|
|
28
35
|
### store connectors partitioned by
|
29
36
|
### type, label for reuse
|
@@ -321,7 +328,7 @@ def load_plugin_connectors():
|
|
321
328
|
continue
|
322
329
|
with open(plugin.__file__, encoding='utf-8') as f:
|
323
330
|
text = f.read()
|
324
|
-
if 'make_connector' in text:
|
331
|
+
if 'make_connector' in text or 'Connector' in text:
|
325
332
|
to_import.append(plugin.name)
|
326
333
|
if not to_import:
|
327
334
|
return
|
@@ -42,9 +42,13 @@ def cli(
|
|
42
42
|
env = copy.deepcopy(dict(os.environ))
|
43
43
|
env[f'MRSM_SQL_{self.label.upper()}'] = json.dumps(self.meta)
|
44
44
|
cli_code = (
|
45
|
+
"import sys\n"
|
45
46
|
"import meerschaum as mrsm\n"
|
46
47
|
f"conn = mrsm.get_connector('sql:{self.label}')\n"
|
47
|
-
|
48
|
+
"success, msg = conn._cli_exit()\n"
|
49
|
+
"mrsm.pprint((success, msg))\n"
|
50
|
+
"if not success:\n"
|
51
|
+
" raise Exception(msg)"
|
48
52
|
)
|
49
53
|
try:
|
50
54
|
_ = venv_exec(cli_code, venv=None, debug=debug, capture_output=False)
|
@@ -91,6 +95,8 @@ def _cli_exit(
|
|
91
95
|
cli_arg_str = self.DATABASE_URL
|
92
96
|
if self.flavor in ('sqlite', 'duckdb'):
|
93
97
|
cli_arg_str = str(self.database)
|
98
|
+
if cli_arg_str.startswith('postgresql+psycopg://'):
|
99
|
+
cli_arg_str = cli_arg_str.replace('postgresql+psycopg://', 'postgresql://')
|
94
100
|
|
95
101
|
### Define the script to execute to launch the CLI.
|
96
102
|
### The `mssqlcli` script is manually written to avoid telemetry
|
@@ -385,6 +385,9 @@ def get_create_index_queries(
|
|
385
385
|
-------
|
386
386
|
A dictionary of column names mapping to lists of queries.
|
387
387
|
"""
|
388
|
+
### NOTE: Due to recent breaking changes in DuckDB, indices don't behave properly.
|
389
|
+
if self.flavor == 'duckdb':
|
390
|
+
return {}
|
388
391
|
from meerschaum.utils.sql import (
|
389
392
|
sql_item_name,
|
390
393
|
get_distinct_col_count,
|
@@ -554,6 +557,9 @@ def get_drop_index_queries(
|
|
554
557
|
-------
|
555
558
|
A dictionary of column names mapping to lists of queries.
|
556
559
|
"""
|
560
|
+
### NOTE: Due to breaking changes within DuckDB, indices must be skipped.
|
561
|
+
if self.flavor == 'duckdb':
|
562
|
+
return {}
|
557
563
|
if not pipe.exists(debug=debug):
|
558
564
|
return {}
|
559
565
|
from meerschaum.utils.sql import sql_item_name, table_exists, hypertable_queries
|
meerschaum/core/Pipe/__init__.py
CHANGED
@@ -436,6 +436,11 @@ class Pipe:
|
|
436
436
|
def __repr__(self, **kw) -> str:
|
437
437
|
return pipe_repr(self, **kw)
|
438
438
|
|
439
|
+
def __pt_repr__(self):
|
440
|
+
from meerschaum.utils.packages import attempt_import
|
441
|
+
prompt_toolkit_formatted_text = attempt_import('prompt_toolkit.formatted_text', lazy=False)
|
442
|
+
return prompt_toolkit_formatted_text.ANSI(self.__repr__())
|
443
|
+
|
439
444
|
def __getstate__(self) -> Dict[str, Any]:
|
440
445
|
"""
|
441
446
|
Define the state dictionary (pickling).
|
meerschaum/core/Pipe/_sync.py
CHANGED
@@ -215,9 +215,8 @@ def sync(
|
|
215
215
|
|
216
216
|
### Activate and invoke `sync(pipe)` for plugin connectors with `sync` methods.
|
217
217
|
try:
|
218
|
-
if p.connector
|
219
|
-
|
220
|
-
with Venv(connector_plugin, debug=debug):
|
218
|
+
if getattr(p.connector, 'sync', None) is not None:
|
219
|
+
with Venv(get_connector_plugin(p.connector), debug=debug):
|
221
220
|
return_tuple = p.connector.sync(p, debug=debug, **kw)
|
222
221
|
p._exists = None
|
223
222
|
if not isinstance(return_tuple, tuple):
|