meerschaum 2.7.5__py3-none-any.whl → 2.7.7__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. meerschaum/_internal/shell/Shell.py +4 -6
  2. meerschaum/_internal/shell/ShellCompleter.py +6 -5
  3. meerschaum/actions/clear.py +6 -3
  4. meerschaum/actions/copy.py +33 -27
  5. meerschaum/actions/drop.py +100 -22
  6. meerschaum/actions/index.py +71 -0
  7. meerschaum/actions/register.py +8 -12
  8. meerschaum/actions/sql.py +1 -1
  9. meerschaum/actions/sync.py +22 -18
  10. meerschaum/api/dash/pipes.py +2 -3
  11. meerschaum/api/routes/_pipes.py +18 -0
  12. meerschaum/api/routes/_plugins.py +1 -1
  13. meerschaum/api/routes/_users.py +62 -61
  14. meerschaum/config/_default.py +5 -0
  15. meerschaum/config/_version.py +1 -1
  16. meerschaum/connectors/api/_misc.py +3 -2
  17. meerschaum/connectors/api/_pipes.py +28 -9
  18. meerschaum/connectors/sql/_SQLConnector.py +7 -3
  19. meerschaum/connectors/sql/_create_engine.py +1 -1
  20. meerschaum/connectors/sql/_fetch.py +4 -9
  21. meerschaum/connectors/sql/_instance.py +3 -3
  22. meerschaum/connectors/sql/_pipes.py +292 -76
  23. meerschaum/connectors/sql/_plugins.py +11 -16
  24. meerschaum/connectors/sql/_sql.py +13 -9
  25. meerschaum/connectors/sql/_uri.py +9 -9
  26. meerschaum/connectors/sql/_users.py +10 -12
  27. meerschaum/connectors/sql/tables/__init__.py +13 -14
  28. meerschaum/core/Pipe/__init__.py +12 -2
  29. meerschaum/core/Pipe/_attributes.py +32 -38
  30. meerschaum/core/Pipe/_drop.py +73 -2
  31. meerschaum/core/Pipe/_index.py +68 -0
  32. meerschaum/jobs/_Job.py +1 -0
  33. meerschaum/plugins/__init__.py +7 -3
  34. meerschaum/utils/daemon/Daemon.py +5 -1
  35. meerschaum/utils/daemon/__init__.py +2 -2
  36. meerschaum/utils/dtypes/sql.py +2 -2
  37. meerschaum/utils/misc.py +7 -6
  38. meerschaum/utils/packages/__init__.py +31 -27
  39. meerschaum/utils/packages/_packages.py +1 -1
  40. meerschaum/utils/prompt.py +54 -36
  41. meerschaum/utils/sql.py +80 -34
  42. meerschaum/utils/venv/__init__.py +12 -3
  43. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/METADATA +17 -5
  44. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/RECORD +50 -48
  45. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/WHEEL +1 -1
  46. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/LICENSE +0 -0
  47. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/NOTICE +0 -0
  48. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/entry_points.txt +0 -0
  49. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/top_level.txt +0 -0
  50. {meerschaum-2.7.5.dist-info → meerschaum-2.7.7.dist-info}/zip-safe +0 -0
@@ -742,8 +742,7 @@ class Shell(cmd.Cmd):
742
742
  """
743
743
  from meerschaum import get_connector
744
744
  from meerschaum.connectors.parse import parse_instance_keys
745
- from meerschaum.utils.warnings import warn, info
746
- from meerschaum.utils.misc import remove_ansi
745
+ from meerschaum.utils.warnings import info
747
746
 
748
747
  if action is None:
749
748
  action = []
@@ -829,7 +828,7 @@ class Shell(cmd.Cmd):
829
828
  """
830
829
  from meerschaum import get_connector
831
830
  from meerschaum.connectors.parse import parse_repo_keys
832
- from meerschaum.utils.warnings import warn, info
831
+ from meerschaum.utils.warnings import info
833
832
 
834
833
  if action is None:
835
834
  action = []
@@ -878,7 +877,6 @@ class Shell(cmd.Cmd):
878
877
 
879
878
  Note that executors are API instances.
880
879
  """
881
- from meerschaum import get_connector
882
880
  from meerschaum.connectors.parse import parse_executor_keys
883
881
  from meerschaum.utils.warnings import warn, info
884
882
  from meerschaum.jobs import get_executor_keys_from_context
@@ -894,7 +892,7 @@ class Shell(cmd.Cmd):
894
892
  executor_keys = get_executor_keys_from_context()
895
893
 
896
894
  if executor_keys == 'systemd' and get_executor_keys_from_context() != 'systemd':
897
- warn(f"Cannot execute via `systemd`, falling back to `local`...", stack=False)
895
+ warn("Cannot execute via `systemd`, falling back to `local`...", stack=False)
898
896
  executor_keys = 'local'
899
897
 
900
898
  conn = parse_executor_keys(executor_keys, debug=debug)
@@ -935,7 +933,7 @@ class Shell(cmd.Cmd):
935
933
  if args['action'][0] not in shell_attrs['_actions']:
936
934
  try:
937
935
  print(textwrap.dedent(getattr(self, f"do_{args['action'][0]}").__doc__))
938
- except Exception as e:
936
+ except Exception:
939
937
  print(f"No help on '{args['action'][0]}'.")
940
938
  return ""
941
939
  parse_help(args)
@@ -7,13 +7,15 @@ Implement the prompt_toolkit Completer base class.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
- from prompt_toolkit.completion import Completer, Completion
11
- from meerschaum.utils.typing import Optional
12
- from meerschaum.actions import get_shell, get_completer, get_main_action_name, get_action
10
+ from meerschaum.actions import get_shell, get_main_action_name, get_action
13
11
  from meerschaum._internal.arguments import parse_line
14
12
 
15
13
  from meerschaum.utils.packages import attempt_import, ensure_readline
16
- prompt_toolkit = attempt_import('prompt_toolkit', lazy=False, install=True)
14
+
15
+ prompt_toolkit_completion = attempt_import('prompt_toolkit.completion', lazy=False, install=True)
16
+ Completer = prompt_toolkit_completion.Completer
17
+ Completion = prompt_toolkit_completion.Completion
18
+
17
19
 
18
20
  class ShellCompleter(Completer):
19
21
  """
@@ -30,7 +32,6 @@ class ShellCompleter(Completer):
30
32
  yielded = []
31
33
  ensure_readline()
32
34
  parts = document.text.split('-')
33
- ends_with_space = parts[0].endswith(' ')
34
35
  last_action_line = parts[0].split('+')[-1]
35
36
  part_0_subbed_spaces = last_action_line.replace(' ', '_')
36
37
  parsed_text = (part_0_subbed_spaces + '-'.join(parts[1:]))
@@ -130,12 +130,15 @@ def _ask_with_rowcounts(
130
130
  )
131
131
 
132
132
 
133
- pipes_rowcounts = {p: p.get_rowcount(begin=begin, end=end, debug=debug) for p in pipes}
133
+ pipes_rowcounts = {
134
+ pipe: pipe.get_rowcount(begin=begin, end=end, debug=debug)
135
+ for pipe in pipes
136
+ }
134
137
  print_options(
135
- [str(p) + f'\n{rc}\n' for p, rc in pipes_rowcounts.items()],
138
+ [str(pipe) + f'\n{rowcount:,}\n' for pipe, rowcount in pipes_rowcounts.items()],
136
139
  header='Number of Rows to be Deleted'
137
140
  )
138
- total_num_rows = sum([rc for p, rc in pipes_rowcounts.items()])
141
+ total_num_rows = sum([rowcount for rowcount in pipes_rowcounts.values()])
139
142
  question = (
140
143
  f"Are you sure you want to delete {total_num_rows:,} rows across {len(pipes)} pipe"
141
144
  + ('s' if len(pipes) != 1 else '')
@@ -7,7 +7,7 @@ Functions for copying elements.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
- from meerschaum.utils.typing import Union, Any, Sequence, SuccessTuple, Optional, Tuple, List
10
+ from meerschaum.utils.typing import Any, SuccessTuple, Optional, List
11
11
 
12
12
  def copy(
13
13
  action: Optional[List[str]] = None,
@@ -69,44 +69,53 @@ def _copy_pipes(
69
69
  Copy pipes' attributes and make new pipes.
70
70
  """
71
71
  from meerschaum import get_pipes, Pipe
72
- from meerschaum.utils.prompt import prompt, yes_no
72
+ from meerschaum.utils.prompt import prompt, yes_no, get_connectors_completer
73
73
  from meerschaum.utils.warnings import warn
74
74
  from meerschaum.utils.formatting import print_tuple
75
75
  from meerschaum.utils.formatting._shell import clear_screen
76
76
  pipes = get_pipes(as_list=True, **kw)
77
77
  successes = 0
78
- for p in pipes:
79
- ck = prompt(f"Connector keys for copy of {p}:", default=p.connector_keys)
80
- mk = prompt(f"Metric key for copy of {p}:", default=p.metric_key)
81
- lk = prompt(f"Location key for copy of {p} ('None' to omit):", default=str(p.location_key))
78
+ for pipe in pipes:
79
+ ck = prompt(
80
+ f"Connector keys for copy of {pipe}:",
81
+ default=pipe.connector_keys,
82
+ completer=get_connectors_completer(),
83
+ )
84
+ mk = prompt(f"Metric key for copy of {pipe}:", default=pipe.metric_key)
85
+ lk = prompt(
86
+ f"Location key for copy of {pipe} ('None' to omit):",
87
+ default=str(pipe.location_key),
88
+ )
82
89
  if lk in ('', 'None', '[None]'):
83
90
  lk = None
84
- _new_pipe = Pipe(
85
- ck, mk, lk,
86
- parameters=p.parameters.copy(),
87
- )
91
+
88
92
  instance_keys = prompt(
89
- f"Meerschaum instance to store the new {_new_pipe}:",
90
- default=p.instance_keys
93
+ f"Meerschaum instance for copy of {pipe}:",
94
+ default=pipe.instance_keys
91
95
  )
92
- _new_pipe.instance_keys = instance_keys
93
- if _new_pipe.get_id(debug=debug) is not None:
94
- warn(f"New {_new_pipe} already exists. Skipping...", stack=False)
96
+ new_pipe = Pipe(
97
+ ck, mk, lk,
98
+ instance=instance_keys,
99
+ parameters=pipe.parameters.copy(),
100
+ )
101
+
102
+ if new_pipe.get_id(debug=debug) is not None:
103
+ warn(f"{new_pipe} already exists. Skipping...", stack=False)
95
104
  continue
96
- _register_success_tuple = _new_pipe.register(debug=debug)
105
+ _register_success_tuple = new_pipe.register(debug=debug)
97
106
  if not _register_success_tuple[0]:
98
- warn(f"Failed to register new {_new_pipe}.", stack=False)
107
+ warn(f"Failed to register new {new_pipe}.", stack=False)
99
108
  continue
100
109
 
101
110
  clear_screen(debug=debug)
102
111
  successes += 1
103
112
  print_tuple(
104
- (True, f"Successfully copied attributes of {p} " + f" into {_new_pipe}.")
113
+ (True, f"Successfully copied attributes of {pipe} " + f" into {new_pipe}.")
105
114
  )
106
115
  if (
107
116
  force or yes_no(
108
117
  (
109
- f"Do you want to copy data from {p} into {_new_pipe}?\n\n"
118
+ f"Do you want to copy data from {pipe} into {new_pipe}?\n\n"
110
119
  + "If you specified `--begin`, `--end` or `--params`, data will be filtered."
111
120
  ),
112
121
  noask=noask,
@@ -114,8 +123,8 @@ def _copy_pipes(
114
123
  default='n',
115
124
  )
116
125
  ):
117
- _new_pipe.sync(
118
- p.get_data(
126
+ new_pipe.sync(
127
+ pipe.get_data(
119
128
  debug=debug,
120
129
  as_iterator=True,
121
130
  **kw
@@ -142,17 +151,14 @@ def _copy_connectors(
142
151
  ) -> SuccessTuple:
143
152
  """
144
153
  Create a new connector from an existing one.
145
-
146
154
  """
147
- import os, pathlib
148
155
  from meerschaum.utils.prompt import yes_no, prompt
149
156
  from meerschaum.connectors.parse import parse_connector_keys
150
157
  from meerschaum.config import _config, get_config
151
- from meerschaum.config._edit import write_config
152
- from meerschaum.utils.warnings import info, warn
158
+ from meerschaum.utils.warnings import info
153
159
  from meerschaum.utils.formatting import pprint
154
160
  from meerschaum.actions import get_action
155
- cf = _config()
161
+ _ = _config()
156
162
  if action is None:
157
163
  action = []
158
164
  if connector_keys is None:
@@ -170,7 +176,7 @@ def _copy_connectors(
170
176
 
171
177
  try:
172
178
  conn = parse_connector_keys(ck)
173
- except Exception as e:
179
+ except Exception:
174
180
  return False, f"Unable to parse connector '{ck}'."
175
181
 
176
182
  if len(_keys) == 2:
@@ -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}"))
@@ -275,12 +275,14 @@ def _sync_pipes(
275
275
  import time
276
276
  import os
277
277
  import contextlib
278
+ from datetime import timedelta
278
279
 
279
280
  from meerschaum.utils.warnings import warn, info
280
281
  from meerschaum.utils.formatting._shell import progress
281
282
  from meerschaum.utils.formatting._shell import clear_screen
282
283
  from meerschaum.utils.formatting import print_pipes_results
283
284
  from meerschaum.config.static import STATIC_CONFIG
285
+ from meerschaum.utils.misc import interval_str
284
286
 
285
287
  noninteractive_val = os.environ.get(STATIC_CONFIG['environment']['noninteractive'], None)
286
288
  noninteractive = str(noninteractive_val).lower() in ('1', 'true', 'yes')
@@ -321,7 +323,7 @@ def _sync_pipes(
321
323
  for pipe, (_success, _msg) in results_dict.items()
322
324
  if not _success
323
325
  ]
324
- except Exception as e:
326
+ except Exception:
325
327
  import traceback
326
328
  traceback.print_exc()
327
329
  warn(
@@ -351,9 +353,9 @@ def _sync_pipes(
351
353
  success_msg = (
352
354
  "Successfully spawned threads for pipes:"
353
355
  if unblock
354
- else f"Successfully synced pipes:"
356
+ else "Successfully synced pipes:"
355
357
  )
356
- fail_msg = f"Failed to sync pipes:"
358
+ fail_msg = "Failed to sync pipes:"
357
359
  if results_dict:
358
360
  print_pipes_results(
359
361
  results_dict,
@@ -362,8 +364,10 @@ def _sync_pipes(
362
364
  nopretty = nopretty,
363
365
  )
364
366
 
367
+ lap_duration_text = interval_str(timedelta(seconds=(lap_end - lap_begin)))
368
+
365
369
  msg = (
366
- f"It took {round(lap_end - lap_begin, 2)} seconds to sync " +
370
+ f"It took {lap_duration_text} to sync " +
367
371
  f"{len(success_pipes) + len(failure_pipes)} pipe" +
368
372
  ("s" if (len(success_pipes) + len(failure_pipes)) != 1 else "") + "\n" +
369
373
  f" ({len(success_pipes)} succeeded, {len(failure_pipes)} failed)."
@@ -385,26 +389,26 @@ def _sync_pipes(
385
389
 
386
390
 
387
391
  def _wrap_pipe(
388
- pipe,
389
- unblock: bool = False,
390
- force: bool = False,
391
- debug: bool = False,
392
- min_seconds: int = 1,
393
- workers = None,
394
- verify: bool = False,
395
- deduplicate: bool = False,
396
- bounded: Optional[bool] = None,
397
- chunk_interval: Union[timedelta, int, None] = None,
398
- **kw
399
- ):
392
+ pipe,
393
+ unblock: bool = False,
394
+ force: bool = False,
395
+ debug: bool = False,
396
+ min_seconds: int = 1,
397
+ workers = None,
398
+ verify: bool = False,
399
+ deduplicate: bool = False,
400
+ bounded: Optional[bool] = None,
401
+ chunk_interval: Union[timedelta, int, None] = None,
402
+ **kw
403
+ ):
400
404
  """
401
405
  Wrapper function for handling exceptions.
402
406
  """
403
407
  import time
404
408
  import traceback
405
- from datetime import datetime, timedelta, timezone
409
+ from datetime import datetime, timezone
406
410
  import meerschaum as mrsm
407
- from meerschaum.utils.typing import is_success_tuple, SuccessTuple
411
+ from meerschaum.utils.typing import is_success_tuple
408
412
  from meerschaum.connectors import get_connector_plugin
409
413
  from meerschaum.utils.venv import Venv
410
414
  from meerschaum.plugins import _pre_sync_hooks, _post_sync_hooks
@@ -12,7 +12,6 @@ import shlex
12
12
  from textwrap import dedent
13
13
  from urllib.parse import urlencode
14
14
 
15
- from dash.dependencies import Input, Output, State
16
15
  from meerschaum.utils.typing import List, Optional, Dict, Any, Tuple, Union
17
16
  from meerschaum.utils.misc import string_to_dict
18
17
  from meerschaum.utils.packages import attempt_import, import_dcc, import_html, import_pandas
@@ -76,7 +75,7 @@ def keys_from_state(
76
75
  try:
77
76
  # params = string_to_dict(state['params-textarea.value'])
78
77
  params = string_to_dict(state['search-parameters-editor.value'])
79
- except Exception as e:
78
+ except Exception:
80
79
  params = None
81
80
  else:
82
81
  params = None
@@ -506,7 +505,7 @@ def accordion_items_from_pipe(
506
505
 
507
506
  stats_rows = []
508
507
  if rowcount is not None:
509
- stats_rows.append(html.Tr([html.Td("Row-count"), html.Td(f"{rowcount}")]))
508
+ stats_rows.append(html.Tr([html.Td("Row Count"), html.Td(f"{rowcount:,}")]))
510
509
  if interval is not None:
511
510
  stats_rows.append(
512
511
  html.Tr([html.Td("Timespan"), html.Td(humanfriendly.format_timespan(interval))])
@@ -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()