meerschaum 2.7.6__py3-none-any.whl → 2.7.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.
Files changed (33) hide show
  1. meerschaum/actions/drop.py +100 -22
  2. meerschaum/actions/index.py +71 -0
  3. meerschaum/actions/register.py +8 -12
  4. meerschaum/actions/sql.py +1 -1
  5. meerschaum/api/routes/_pipes.py +18 -0
  6. meerschaum/api/routes/_plugins.py +1 -1
  7. meerschaum/api/routes/_users.py +62 -61
  8. meerschaum/config/_version.py +1 -1
  9. meerschaum/connectors/api/_pipes.py +20 -0
  10. meerschaum/connectors/sql/_SQLConnector.py +6 -3
  11. meerschaum/connectors/sql/_create_engine.py +1 -1
  12. meerschaum/connectors/sql/_fetch.py +4 -9
  13. meerschaum/connectors/sql/_instance.py +3 -3
  14. meerschaum/connectors/sql/_pipes.py +255 -66
  15. meerschaum/connectors/sql/_plugins.py +11 -16
  16. meerschaum/connectors/sql/_sql.py +4 -8
  17. meerschaum/connectors/sql/_uri.py +9 -9
  18. meerschaum/connectors/sql/_users.py +10 -12
  19. meerschaum/connectors/sql/tables/__init__.py +13 -14
  20. meerschaum/core/Pipe/__init__.py +12 -2
  21. meerschaum/core/Pipe/_attributes.py +32 -38
  22. meerschaum/core/Pipe/_drop.py +73 -2
  23. meerschaum/core/Pipe/_index.py +68 -0
  24. meerschaum/utils/dtypes/sql.py +2 -2
  25. meerschaum/utils/sql.py +80 -34
  26. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/METADATA +14 -2
  27. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/RECORD +33 -31
  28. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/WHEEL +1 -1
  29. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/LICENSE +0 -0
  30. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/NOTICE +0 -0
  31. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/entry_points.txt +0 -0
  32. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/top_level.txt +0 -0
  33. {meerschaum-2.7.6.dist-info → meerschaum-2.7.7.dist-info}/zip-safe +0 -0
@@ -6,52 +6,65 @@ Functions for dropping elements
6
6
  """
7
7
 
8
8
  from __future__ import annotations
9
- from meerschaum.utils.typing import SuccessTuple, Union, Any, Optional, Sequence, List
9
+ from meerschaum.utils.typing import SuccessTuple, Any, Optional, List
10
+
10
11
 
11
12
  def drop(
12
- action: Optional[List[str]] = None,
13
- **kw: Any
14
- ) -> SuccessTuple:
13
+ action: Optional[List[str]] = None,
14
+ **kw: Any
15
+ ) -> SuccessTuple:
15
16
  """
16
17
  Drop pipe data (maintaining registration) or tables.
17
18
  """
18
19
  from meerschaum.actions import choose_subaction
19
20
  options = {
20
21
  'pipes' : _drop_pipes,
22
+ 'indices': _drop_indices,
23
+ 'index': _drop_indices,
24
+ 'indexes': _drop_indices,
21
25
  }
22
26
  return choose_subaction(action, options, **kw)
23
27
 
24
28
 
25
29
  def _drop_pipes(
26
- action: Optional[List[str]] = None,
27
- yes: bool = False,
28
- force: bool = False,
29
- noask: bool = False,
30
- debug: bool = False,
31
- **kw: Any
32
- ) -> SuccessTuple:
30
+ action: Optional[List[str]] = None,
31
+ yes: bool = False,
32
+ force: bool = False,
33
+ noask: bool = False,
34
+ debug: bool = False,
35
+ **kw: Any
36
+ ) -> SuccessTuple:
33
37
  """
34
38
  Drop pipes' tables but keep pipe metadata registration.
35
39
  """
36
- from meerschaum.utils.prompt import prompt, yes_no
40
+ from meerschaum.utils.prompt import yes_no
37
41
  from meerschaum import get_pipes
38
42
  from meerschaum.utils.warnings import warn
39
43
  from meerschaum.utils.debug import dprint
40
44
  from meerschaum.utils.formatting import pprint
45
+
41
46
  pipes = get_pipes(as_list=True, debug=debug, **kw)
42
47
  if len(pipes) == 0:
43
48
  return False, "No pipes to drop."
49
+
44
50
  question = (
45
51
  "Are you sure you want to drop these tables?\n "
46
- + "Data will be lost and will need to be resynced.\n\n"
52
+ "Data will be lost and will need to be resynced.\n\n"
47
53
  )
48
- for p in pipes:
49
- question += f" - {p.target}" + "\n"
54
+ seen_targets = set()
55
+ for pipe in pipes:
56
+ target = pipe.target
57
+ if target in seen_targets:
58
+ continue
59
+ question += f" - {target}" + "\n"
60
+ seen_targets.add(target)
61
+
50
62
  question += '\n'
51
63
  if force:
52
64
  answer = True
53
65
  else:
54
66
  answer = yes_no(question, default='n', noask=noask, yes=yes)
67
+
55
68
  if not answer:
56
69
  return False, "No pipes were dropped."
57
70
 
@@ -59,22 +72,87 @@ def _drop_pipes(
59
72
  successes, fails = 0, 0
60
73
  msg = ""
61
74
 
62
- for p in pipes:
63
- success_tup = p.drop(debug=debug)
64
- success_dict[p] = success_tup[1]
65
- if success_tup[0]:
75
+ for pipe in pipes:
76
+ drop_success, drop_msg = pipe.drop(debug=debug)
77
+ success_dict[pipe] = drop_msg
78
+ if drop_success:
66
79
  successes += 1
67
80
  else:
68
81
  fails += 1
69
- warn(success_tup[1], stack=False)
82
+ warn(drop_msg, stack=False)
70
83
 
71
84
  if debug:
72
85
  dprint("Results for dropping pipes.")
73
86
  pprint(success_dict)
74
87
 
75
88
  msg = (
76
- f"Finished dropping {len(pipes)} pipes\n" +
77
- f" ({successes} succeeded, {fails} failed)."
89
+ f"Finished dropping {len(pipes)} pipes"
90
+ + ('s' if len(pipes) != 1 else '')
91
+ + f"\n ({successes} succeeded, {fails} failed)."
92
+ )
93
+ return successes > 0, msg
94
+
95
+
96
+ def _drop_indices(
97
+ action: Optional[List[str]] = None,
98
+ yes: bool = False,
99
+ force: bool = False,
100
+ noask: bool = False,
101
+ debug: bool = False,
102
+ **kw: Any
103
+ ) -> SuccessTuple:
104
+ """
105
+ Drop pipes' tables but keep pipe metadata registration.
106
+ """
107
+ from meerschaum.utils.prompt import yes_no
108
+ from meerschaum import get_pipes
109
+ from meerschaum.utils.warnings import warn
110
+ from meerschaum.utils.debug import dprint
111
+ from meerschaum.utils.formatting import pprint
112
+
113
+ pipes = get_pipes(as_list=True, debug=debug, **kw)
114
+ if len(pipes) == 0:
115
+ return False, "No pipes to drop."
116
+
117
+ question = "Are you sure you want to drop these indices?\n"
118
+ for pipe in pipes:
119
+ indices = pipe.get_indices()
120
+ if not indices:
121
+ continue
122
+ question += f"\n{pipe}\n"
123
+ for ix_key, index_name in indices.items():
124
+ question += f" - {index_name}\n"
125
+
126
+ question += '\n'
127
+ if force:
128
+ answer = True
129
+ else:
130
+ answer = yes_no(question, default='n', noask=noask, yes=yes)
131
+
132
+ if not answer:
133
+ return False, "No pipes were dropped."
134
+
135
+ success_dict = {}
136
+ successes, fails = 0, 0
137
+ msg = ""
138
+
139
+ for pipe in pipes:
140
+ drop_success, drop_msg = pipe.drop_indices(debug=debug)
141
+ success_dict[pipe] = drop_msg
142
+ if drop_success:
143
+ successes += 1
144
+ else:
145
+ fails += 1
146
+ warn(drop_msg, stack=False)
147
+
148
+ if debug:
149
+ dprint("Results for dropping indices.")
150
+ pprint(success_dict)
151
+
152
+ msg = (
153
+ f"Finished dropping indices for {len(pipes)} pipe"
154
+ + ('s' if len(pipes) != 1 else '')
155
+ + f"\n ({successes} succeeded, {fails} failed)."
78
156
  )
79
157
  return successes > 0, msg
80
158
 
@@ -0,0 +1,71 @@
1
+ #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # vim:fenc=utf-8
4
+
5
+ """
6
+ Functions for indexing tables.
7
+ """
8
+
9
+ from __future__ import annotations
10
+ from meerschaum.utils.typing import SuccessTuple, Any, Optional, List
11
+
12
+
13
+ def index(
14
+ action: Optional[List[str]] = None,
15
+ **kw: Any
16
+ ) -> SuccessTuple:
17
+ """
18
+ Create pipes' indices.
19
+ """
20
+ from meerschaum.actions import choose_subaction
21
+ options = {
22
+ 'pipes' : _index_pipes,
23
+ }
24
+ return choose_subaction(action, options, **kw)
25
+
26
+
27
+ def _index_pipes(
28
+ action: Optional[List[str]] = None,
29
+ yes: bool = False,
30
+ force: bool = False,
31
+ noask: bool = False,
32
+ debug: bool = False,
33
+ **kw: Any
34
+ ) -> SuccessTuple:
35
+ """
36
+ Create pipes' indices.
37
+ """
38
+ from meerschaum import get_pipes
39
+ from meerschaum.utils.warnings import warn, info
40
+
41
+ pipes = get_pipes(as_list=True, debug=debug, **kw)
42
+ if len(pipes) == 0:
43
+ return False, "No pipes to index."
44
+
45
+ success_dict = {}
46
+ successes, fails = 0, 0
47
+ msg = ""
48
+
49
+ for pipe in pipes:
50
+ info(f"Creating indices for {pipe}...")
51
+ index_success, index_msg = pipe.create_indices(debug=debug)
52
+ success_dict[pipe] = index_msg
53
+ if index_success:
54
+ successes += 1
55
+ else:
56
+ fails += 1
57
+ warn(index_msg, stack=False)
58
+
59
+ msg = (
60
+ f"Finished indexing {len(pipes)} pipes"
61
+ + ('s' if len(pipes) != 1 else '')
62
+ + f"\n ({successes} succeeded, {fails} failed)."
63
+ )
64
+ return successes > 0, msg
65
+
66
+
67
+ ### NOTE: This must be the final statement of the module.
68
+ ### Any subactions added below these lines will not
69
+ ### be added to the `help` docstring.
70
+ from meerschaum.actions import choices_docstring as _choices_docstring
71
+ index.__doc__ += _choices_docstring('index')
@@ -10,6 +10,7 @@ from __future__ import annotations
10
10
  import meerschaum as mrsm
11
11
  from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Dict
12
12
 
13
+
13
14
  def register(
14
15
  action: Optional[List[str]] = None,
15
16
  **kw: Any
@@ -70,10 +71,9 @@ def _register_pipes(
70
71
  `connector_keys` and `metric_keys`.
71
72
  If `location_keys` is empty, assume [`None`].
72
73
  """
73
- from meerschaum import get_pipes, get_connector
74
+ from meerschaum import get_pipes
74
75
  from meerschaum.utils.debug import dprint
75
- from meerschaum.utils.warnings import warn, info
76
- from meerschaum.utils.misc import items_str
76
+ from meerschaum.utils.warnings import warn
77
77
  from meerschaum.config._patch import apply_patch_to_config
78
78
 
79
79
  if connector_keys is None:
@@ -164,10 +164,8 @@ def _register_plugins(
164
164
  from meerschaum.utils.debug import dprint
165
165
  from meerschaum.plugins import reload_plugins, get_plugins_names
166
166
  from meerschaum.connectors.parse import parse_repo_keys
167
- from meerschaum.config import get_config
168
- from meerschaum.utils.warnings import warn, error, info
167
+ from meerschaum.utils.warnings import warn, info
169
168
  from meerschaum.core import Plugin
170
- from meerschaum import get_connector
171
169
  from meerschaum.utils.formatting import print_tuple
172
170
  from meerschaum.utils.prompt import prompt, yes_no
173
171
 
@@ -179,7 +177,7 @@ def _register_plugins(
179
177
  repo_connector = parse_repo_keys(repository)
180
178
  if repo_connector.__dict__.get('type', None) != 'api':
181
179
  return False, (
182
- f"Can only upload plugins to the Meerschaum API." +
180
+ "Can only upload plugins to the Meerschaum API." +
183
181
  f"Connector '{repo_connector}' is of type " +
184
182
  f"'{repo_connector.get('type', type(repo_connector))}'."
185
183
  )
@@ -283,13 +281,11 @@ def _register_users(
283
281
  """
284
282
  from meerschaum.config import get_config
285
283
  from meerschaum.config.static import STATIC_CONFIG
286
- from meerschaum import get_connector
287
284
  from meerschaum.connectors.parse import parse_instance_keys
288
- from meerschaum.utils.debug import dprint
289
- from meerschaum.utils.warnings import warn, error, info
285
+ from meerschaum.utils.warnings import warn, info
290
286
  from meerschaum.core import User
291
287
  from meerschaum.utils.formatting import print_tuple
292
- from meerschaum.utils.prompt import prompt, get_password, get_email
288
+ from meerschaum.utils.prompt import get_password, get_email
293
289
  if mrsm_instance is None:
294
290
  mrsm_instance = get_config('meerschaum', 'instance')
295
291
  instance_connector = parse_instance_keys(mrsm_instance)
@@ -325,7 +321,7 @@ def _register_users(
325
321
  minimum_length = STATIC_CONFIG['users']['min_password_length']
326
322
  )
327
323
  email = get_email(username, allow_omit=True)
328
- except Exception as e:
324
+ except Exception:
329
325
  return False, (
330
326
  "Aborted registering users " +
331
327
  ', '.join(
meerschaum/actions/sql.py CHANGED
@@ -127,7 +127,7 @@ def sql(
127
127
 
128
128
  from meerschaum.utils.packages import attempt_import
129
129
  from meerschaum.utils.formatting import print_tuple, pprint
130
- _ = attempt_import('sqlalchemy.engine.result')
130
+ _ = attempt_import('sqlalchemy.engine.result', lazy=False)
131
131
  if 'sqlalchemy' in str(type(result)):
132
132
  if not nopretty:
133
133
  print_tuple((True, f"Successfully executed query:\n\n{query}"))
@@ -688,3 +688,21 @@ def get_pipe_columns_indices(
688
688
  Return a dictionary of column names and related indices.
689
689
  """
690
690
  return get_pipe(connector_keys, metric_key, location_key).get_columns_indices()
691
+
692
+
693
+ @app.get(
694
+ pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/indices/names',
695
+ tags=['Pipes']
696
+ )
697
+ def get_pipe_index_names(
698
+ connector_keys: str,
699
+ metric_key: str,
700
+ location_key: str,
701
+ curr_user=(
702
+ fastapi.Depends(manager) if not no_auth else None
703
+ ),
704
+ ) -> Dict[str, List[Dict[str, str]]]:
705
+ """
706
+ Return a dictionary of index keys and index names.
707
+ """
708
+ return get_pipe(connector_keys, metric_key, location_key).get_indices()
@@ -29,7 +29,7 @@ from meerschaum.core import Plugin
29
29
  starlette_responses = attempt_import('starlette.responses', warn=False)
30
30
  FileResponse = starlette_responses.FileResponse
31
31
 
32
- sqlalchemy = attempt_import('sqlalchemy')
32
+ sqlalchemy = attempt_import('sqlalchemy', lazy=False)
33
33
  plugins_endpoint = endpoints['plugins']
34
34
 
35
35
  @app.post(plugins_endpoint + '/{name}', tags=['Plugins'])
@@ -7,36 +7,34 @@ Routes for managing users
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
+
10
11
  from meerschaum.utils.typing import (
11
- Optional, Union, SuccessTuple, Any, Mapping, Sequence, Dict, List
12
+ Union, SuccessTuple, Any, Dict, List
12
13
  )
13
14
 
14
15
  from meerschaum.utils.packages import attempt_import
15
16
  from meerschaum.api import (
16
- fastapi, app, endpoints, get_api_connector, pipes, get_pipe,
17
- manager, debug, check_allow_chaining, DISALLOW_CHAINING_MESSAGE,
17
+ fastapi, app, endpoints, get_api_connector, manager,
18
+ debug, check_allow_chaining, DISALLOW_CHAINING_MESSAGE,
18
19
  no_auth, private,
19
20
  )
20
21
  from meerschaum.utils.misc import string_to_dict
21
22
  from meerschaum.config import get_config
22
- from meerschaum.api.tables import get_tables
23
- from starlette.responses import Response, JSONResponse
24
23
  from meerschaum.core import User
25
- import os, pathlib, datetime
26
24
 
27
- import meerschaum.core
28
- sqlalchemy = attempt_import('sqlalchemy')
25
+ sqlalchemy = attempt_import('sqlalchemy', lazy=False)
29
26
  users_endpoint = endpoints['users']
30
27
 
31
28
  import fastapi
32
29
  from fastapi import HTTPException, Form
33
30
 
31
+
34
32
  @app.get(users_endpoint + "/me", tags=['Users'])
35
33
  def read_current_user(
36
- curr_user = (
37
- fastapi.Depends(manager) if not no_auth else None
38
- ),
39
- ) -> Dict[str, Union[str, int]]:
34
+ curr_user = (
35
+ fastapi.Depends(manager) if not no_auth else None
36
+ ),
37
+ ) -> Dict[str, Union[str, int]]:
40
38
  """
41
39
  Get information about the currently logged-in user.
42
40
  """
@@ -58,12 +56,13 @@ def read_current_user(
58
56
  ),
59
57
  }
60
58
 
59
+
61
60
  @app.get(users_endpoint, tags=['Users'])
62
61
  def get_users(
63
- curr_user = (
64
- fastapi.Depends(manager) if private else None
65
- ),
66
- ) -> List[str]:
62
+ curr_user = (
63
+ fastapi.Depends(manager) if private else None
64
+ ),
65
+ ) -> List[str]:
67
66
  """
68
67
  Get a list of the registered users.
69
68
  """
@@ -72,15 +71,15 @@ def get_users(
72
71
 
73
72
  @app.post(users_endpoint + "/register", tags=['Users'])
74
73
  def register_user(
75
- username: str = Form(None),
76
- password: str = Form(None),
77
- attributes: str = Form(None),
78
- type: str = Form(None),
79
- email: str = Form(None),
80
- curr_user = (
81
- fastapi.Depends(manager) if private else None
82
- ),
83
- ) -> SuccessTuple:
74
+ username: str = Form(None),
75
+ password: str = Form(None),
76
+ attributes: str = Form(None),
77
+ type: str = Form(None),
78
+ email: str = Form(None),
79
+ curr_user = (
80
+ fastapi.Depends(manager) if private else None
81
+ ),
82
+ ) -> SuccessTuple:
84
83
  """
85
84
  Register a new user.
86
85
  """
@@ -90,7 +89,7 @@ def register_user(
90
89
  if attributes is not None:
91
90
  try:
92
91
  attributes = string_to_dict(attributes)
93
- except Exception as e:
92
+ except Exception:
94
93
  return False, f"Invalid dictionary string received for attributes."
95
94
 
96
95
  allow_users = get_config('system', 'api', 'permissions', 'registration', 'users')
@@ -114,22 +113,22 @@ def register_user(
114
113
 
115
114
  @app.post(users_endpoint + "/edit", tags=['Users'])
116
115
  def edit_user(
117
- username: str = Form(None),
118
- password: str = Form(None),
119
- type: str = Form(None),
120
- email: str = Form(None),
121
- attributes: str = Form(None),
122
- curr_user = (
123
- fastapi.Depends(manager) if not no_auth else None
124
- ),
125
- ) -> SuccessTuple:
116
+ username: str = Form(None),
117
+ password: str = Form(None),
118
+ type: str = Form(None),
119
+ email: str = Form(None),
120
+ attributes: str = Form(None),
121
+ curr_user = (
122
+ fastapi.Depends(manager) if not no_auth else None
123
+ ),
124
+ ) -> SuccessTuple:
126
125
  """
127
126
  Edit an existing user.
128
127
  """
129
128
  if attributes is not None:
130
129
  try:
131
130
  attributes = string_to_dict(attributes)
132
- except Exception as e:
131
+ except Exception:
133
132
  return False, f"Invalid dictionary string received for attributes."
134
133
 
135
134
  user = User(username, password, email=email, attributes=attributes)
@@ -144,11 +143,11 @@ def edit_user(
144
143
 
145
144
  @app.get(users_endpoint + "/{username}/id", tags=['Users'])
146
145
  def get_user_id(
147
- username : str,
148
- curr_user = (
149
- fastapi.Depends(manager) if not no_auth else None
150
- ),
151
- ) -> Union[int, None]:
146
+ username : str,
147
+ curr_user = (
148
+ fastapi.Depends(manager) if not no_auth else None
149
+ ),
150
+ ) -> Union[int, None]:
152
151
  """
153
152
  Get a user's ID.
154
153
  """
@@ -157,23 +156,24 @@ def get_user_id(
157
156
 
158
157
  @app.get(users_endpoint + "/{username}/attributes", tags=['Users'])
159
158
  def get_user_attributes(
160
- username : str,
161
- curr_user = (
162
- fastapi.Depends(manager) if private else None
163
- ),
164
- ) -> Union[Dict[str, Any], None]:
159
+ username : str,
160
+ curr_user = (
161
+ fastapi.Depends(manager) if private else None
162
+ ),
163
+ ) -> Union[Dict[str, Any], None]:
165
164
  """
166
165
  Get a user's attributes.
167
166
  """
168
167
  return get_api_connector().get_user_attributes(User(username), debug=debug)
169
168
 
169
+
170
170
  @app.delete(users_endpoint + "/{username}", tags=['Users'])
171
171
  def delete_user(
172
- username: str,
173
- curr_user = (
174
- fastapi.Depends(manager) if not no_auth else None
175
- ),
176
- ) -> SuccessTuple:
172
+ username: str,
173
+ curr_user = (
174
+ fastapi.Depends(manager) if not no_auth else None
175
+ ),
176
+ ) -> SuccessTuple:
177
177
  """
178
178
  Delete a user.
179
179
  """
@@ -193,11 +193,11 @@ def delete_user(
193
193
 
194
194
  @app.get(users_endpoint + '/{username}/password_hash', tags=['Users'])
195
195
  def get_user_password_hash(
196
- username: str,
197
- curr_user = (
198
- fastapi.Depends(manager) if not no_auth else None
199
- ),
200
- ) -> str:
196
+ username: str,
197
+ curr_user = (
198
+ fastapi.Depends(manager) if not no_auth else None
199
+ ),
200
+ ) -> str:
201
201
  """
202
202
  If configured to allow chaining, return a user's password_hash.
203
203
  """
@@ -205,13 +205,14 @@ def get_user_password_hash(
205
205
  raise HTTPException(status_code=403, detail=DISALLOW_CHAINING_MESSAGE)
206
206
  return get_api_connector().get_user_password_hash(User(username), debug=debug)
207
207
 
208
+
208
209
  @app.get(users_endpoint + '/{username}/type', tags=['Users'])
209
210
  def get_user_type(
210
- username : str,
211
- curr_user = (
212
- fastapi.Depends(manager) if not no_auth else None
213
- ),
214
- ) -> str:
211
+ username : str,
212
+ curr_user = (
213
+ fastapi.Depends(manager) if not no_auth else None
214
+ ),
215
+ ) -> str:
215
216
  """
216
217
  If configured to allow chaining, return a user's type.
217
218
  """
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "2.7.6"
5
+ __version__ = "2.7.7"
@@ -757,3 +757,23 @@ def get_pipe_columns_indices(
757
757
  warn(response.text)
758
758
  return None
759
759
  return j
760
+
761
+
762
+ def get_pipe_index_names(self, pipe: mrsm.Pipe, debug: bool = False) -> Dict[str, str]:
763
+ """
764
+ Return the templated index names.
765
+ """
766
+ r_url = pipe_r_url(pipe) + '/indices/names'
767
+ response = self.get(
768
+ r_url,
769
+ debug=debug
770
+ )
771
+ j = response.json()
772
+ if isinstance(j, dict) and 'detail' in j and len(j.keys()) == 1:
773
+ warn(j['detail'])
774
+ return None
775
+ if not isinstance(j, dict):
776
+ warn(response.text)
777
+ return None
778
+ return j
779
+
@@ -70,6 +70,9 @@ class SQLConnector(Connector):
70
70
  create_pipe_table_from_df,
71
71
  get_pipe_columns_indices,
72
72
  get_temporary_target,
73
+ create_pipe_indices,
74
+ drop_pipe_indices,
75
+ get_pipe_index_names,
73
76
  )
74
77
  from ._plugins import (
75
78
  register_plugin,
@@ -222,7 +225,7 @@ class SQLConnector(Connector):
222
225
  return None
223
226
 
224
227
  from meerschaum.utils.packages import attempt_import
225
- sqlalchemy_orm = attempt_import('sqlalchemy.orm')
228
+ sqlalchemy_orm = attempt_import('sqlalchemy.orm', lazy=False)
226
229
  session_factory = sqlalchemy_orm.sessionmaker(self.engine)
227
230
  self._Session = sqlalchemy_orm.scoped_session(session_factory)
228
231
 
@@ -290,7 +293,7 @@ class SQLConnector(Connector):
290
293
  Return the metadata bound to this configured schema.
291
294
  """
292
295
  from meerschaum.utils.packages import attempt_import
293
- sqlalchemy = attempt_import('sqlalchemy')
296
+ sqlalchemy = attempt_import('sqlalchemy', lazy=False)
294
297
  if '_metadata' not in self.__dict__:
295
298
  self._metadata = sqlalchemy.MetaData(schema=self.schema)
296
299
  return self._metadata
@@ -368,7 +371,7 @@ class SQLConnector(Connector):
368
371
  self.__dict__['schema'] = None
369
372
  return None
370
373
 
371
- sqlalchemy = mrsm.attempt_import('sqlalchemy')
374
+ sqlalchemy = mrsm.attempt_import('sqlalchemy', lazy=False)
372
375
  _schema = sqlalchemy.inspect(self.engine).default_schema_name
373
376
  self.__dict__['schema'] = _schema
374
377
  return _schema
@@ -186,7 +186,7 @@ def create_engine(
186
186
  """Create a sqlalchemy engine by building the engine string."""
187
187
  from meerschaum.utils.packages import attempt_import
188
188
  from meerschaum.utils.warnings import error, warn
189
- sqlalchemy = attempt_import('sqlalchemy')
189
+ sqlalchemy = attempt_import('sqlalchemy', lazy=False)
190
190
  import urllib
191
191
  import copy
192
192
  ### Install and patch required drivers.