meerschaum 3.0.0rc1__py3-none-any.whl → 3.0.0rc3__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 (66) hide show
  1. meerschaum/_internal/arguments/_parser.py +2 -1
  2. meerschaum/_internal/docs/index.py +49 -2
  3. meerschaum/_internal/shell/Shell.py +5 -4
  4. meerschaum/_internal/static.py +8 -24
  5. meerschaum/actions/bootstrap.py +1 -1
  6. meerschaum/actions/edit.py +6 -3
  7. meerschaum/actions/start.py +1 -1
  8. meerschaum/actions/verify.py +5 -8
  9. meerschaum/api/__init__.py +2 -1
  10. meerschaum/api/dash/__init__.py +0 -2
  11. meerschaum/api/dash/callbacks/__init__.py +1 -0
  12. meerschaum/api/dash/callbacks/dashboard.py +20 -19
  13. meerschaum/api/dash/callbacks/jobs.py +11 -5
  14. meerschaum/api/dash/callbacks/pipes.py +106 -5
  15. meerschaum/api/dash/callbacks/settings/__init__.py +0 -1
  16. meerschaum/api/dash/callbacks/{settings/tokens.py → tokens.py} +1 -1
  17. meerschaum/api/dash/jobs.py +1 -1
  18. meerschaum/api/dash/pages/__init__.py +2 -1
  19. meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
  20. meerschaum/api/dash/pages/pipes.py +4 -3
  21. meerschaum/api/dash/pages/settings/__init__.py +0 -1
  22. meerschaum/api/dash/pages/{settings/tokens.py → tokens.py} +6 -8
  23. meerschaum/api/dash/pipes.py +131 -0
  24. meerschaum/api/dash/tokens.py +28 -31
  25. meerschaum/api/routes/_pipes.py +47 -37
  26. meerschaum/config/_default.py +13 -2
  27. meerschaum/config/_paths.py +1 -0
  28. meerschaum/config/_version.py +1 -1
  29. meerschaum/config/stack/__init__.py +9 -8
  30. meerschaum/connectors/api/_pipes.py +2 -18
  31. meerschaum/connectors/api/_tokens.py +2 -2
  32. meerschaum/connectors/instance/_tokens.py +10 -6
  33. meerschaum/connectors/sql/_SQLConnector.py +14 -0
  34. meerschaum/connectors/sql/_create_engine.py +3 -14
  35. meerschaum/connectors/sql/_pipes.py +175 -185
  36. meerschaum/connectors/sql/_sql.py +38 -20
  37. meerschaum/connectors/sql/tables/__init__.py +237 -122
  38. meerschaum/connectors/valkey/_pipes.py +44 -16
  39. meerschaum/core/Pipe/__init__.py +28 -5
  40. meerschaum/core/Pipe/_attributes.py +273 -46
  41. meerschaum/core/Pipe/_data.py +55 -17
  42. meerschaum/core/Pipe/_dtypes.py +19 -4
  43. meerschaum/core/Pipe/_edit.py +2 -0
  44. meerschaum/core/Pipe/_fetch.py +1 -1
  45. meerschaum/core/Pipe/_sync.py +90 -160
  46. meerschaum/core/Pipe/_verify.py +3 -3
  47. meerschaum/core/Token/_Token.py +4 -5
  48. meerschaum/plugins/bootstrap.py +508 -3
  49. meerschaum/utils/_get_pipes.py +1 -1
  50. meerschaum/utils/dataframe.py +385 -68
  51. meerschaum/utils/debug.py +15 -15
  52. meerschaum/utils/dtypes/__init__.py +387 -22
  53. meerschaum/utils/dtypes/sql.py +327 -31
  54. meerschaum/utils/misc.py +9 -68
  55. meerschaum/utils/packages/__init__.py +7 -21
  56. meerschaum/utils/packages/_packages.py +7 -2
  57. meerschaum/utils/schedule.py +1 -1
  58. meerschaum/utils/sql.py +8 -8
  59. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/METADATA +5 -17
  60. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/RECORD +66 -65
  61. meerschaum-3.0.0rc3.dist-info/licenses/NOTICE +2 -0
  62. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/WHEEL +0 -0
  63. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/entry_points.txt +0 -0
  64. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/licenses/LICENSE +0 -0
  65. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/top_level.txt +0 -0
  66. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc3.dist-info}/zip-safe +0 -0
@@ -11,11 +11,14 @@ from meerschaum.utils.packages import import_html, import_dcc
11
11
  html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
12
12
  import dash_bootstrap_components as dbc
13
13
 
14
- from meerschaum.api.dash.components import download_logs, refresh_jobs_interval
14
+ from meerschaum.api.dash.components import download_logs, refresh_jobs_interval, pages_navbar
15
15
 
16
- layout = dbc.Container([
17
- dcc.Location('job-location'),
18
- html.Div(id='job-output-div'),
19
- download_logs,
20
- refresh_jobs_interval,
21
- ])
16
+ layout = [
17
+ pages_navbar,
18
+ dbc.Container([
19
+ dcc.Location('job-location'),
20
+ html.Div(id='job-output-div'),
21
+ download_logs,
22
+ refresh_jobs_interval,
23
+ ]),
24
+ ]
@@ -7,16 +7,17 @@ Display pipes via a shareable URL.
7
7
 
8
8
  from meerschaum.api import CHECK_UPDATE
9
9
  from meerschaum.utils.packages import import_html, import_dcc
10
- from meerschaum.api.dash.components import download_dataframe, pages_navbar
10
+ from meerschaum.api.dash.components import download_dataframe, pages_navbar, navbar
11
11
 
12
12
  html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHECK_UPDATE)
13
13
  import dash_bootstrap_components as dbc
14
14
 
15
+
15
16
  layout = [
16
17
  pages_navbar,
18
+ dcc.Location('pipes-location'),
19
+ download_dataframe,
17
20
  dbc.Container([
18
- dcc.Location('pipes-location'),
19
- download_dataframe,
20
21
  html.Div(id='pipe-output-div'),
21
22
  ])
22
23
  ]
@@ -6,4 +6,3 @@ Define the layouts for the `settings` pages.
6
6
  """
7
7
 
8
8
  import meerschaum.api.dash.pages.settings.password_reset
9
- import meerschaum.api.dash.pages.settings.tokens
@@ -8,16 +8,13 @@ Define the tokens page layout.
8
8
  import dash_bootstrap_components as dbc
9
9
  import dash.html as html
10
10
  import dash.dcc as dcc
11
- from meerschaum.plugins import web_page
12
11
  from meerschaum._internal.static import STATIC_CONFIG
12
+ from meerschaum.api.dash.components import pages_navbar
13
13
 
14
14
 
15
- @web_page('tokens', login_required=True, page_group='Settings')
16
- def page_layout():
17
- """
18
- Return the layout for the tokens page.
19
- """
20
- return dbc.Container([
15
+ layout = [
16
+ pages_navbar,
17
+ dbc.Container([
21
18
  html.Br(),
22
19
  html.H3('Tokens'),
23
20
  html.Div(id="tokens-alert-div"),
@@ -52,4 +49,5 @@ def page_layout():
52
49
  style={'text-align': 'right'},
53
50
  ),
54
51
  html.Div(id='tokens-output-div'),
55
- ])
52
+ ]),
53
+ ]
@@ -12,6 +12,7 @@ import shlex
12
12
  from textwrap import dedent
13
13
  from urllib.parse import urlencode
14
14
 
15
+ from meerschaum.utils import fetch_pipes_keys
15
16
  from meerschaum.utils.typing import List, Optional, Dict, Any, Tuple, Union
16
17
  from meerschaum.utils.misc import string_to_dict
17
18
  from meerschaum.utils.packages import attempt_import, import_dcc, import_html, import_pandas
@@ -817,3 +818,133 @@ def get_backtrack_text(
817
818
  json_text = '[]'
818
819
 
819
820
  return json.dumps(json.loads(json_text), indent=4, separators=(',', ': '))
821
+
822
+
823
+ def build_pipes_dropdown_keys_row(
824
+ connector_keys: List[str],
825
+ metric_keys: List[str],
826
+ location_keys: List[str],
827
+ tags: List[str],
828
+ pipes: List[mrsm.Pipe],
829
+ instance_connector: mrsm.connectors.InstanceConnector,
830
+ ) -> dbc.Row:
831
+ """
832
+ Return the dropdown keys row for the dedicated pipes page.
833
+ """
834
+ ck_alone = connector_keys and not any([str(x) for x in (tags + metric_keys + location_keys)])
835
+ mk_alone = metric_keys and not any([str(x) for x in (connector_keys + tags + location_keys)])
836
+ lk_alone = location_keys and not any([str(x) for x in (connector_keys + metric_keys + tags)])
837
+ all_keys = fetch_pipes_keys('registered', instance_connector)
838
+ return dbc.Row(
839
+ [
840
+ dbc.Col(
841
+ html.Div(
842
+ [
843
+ dcc.Dropdown(
844
+ id='pipes-connector-keys-dropdown',
845
+ options=(
846
+ sorted(list({pipe.connector_keys for pipe in pipes}))
847
+ if not ck_alone
848
+ else sorted(list({ck for ck, _, _ in all_keys}))
849
+ ),
850
+ value=[str(ck) for ck in connector_keys],
851
+ placeholder='Connectors',
852
+ multi=True,
853
+ ),
854
+ ],
855
+ className='dbc_dark',
856
+ ),
857
+ lg=4,
858
+ md=12,
859
+ sm=12,
860
+ ),
861
+ dbc.Col(
862
+ html.Div(
863
+ [
864
+ dcc.Dropdown(
865
+ id='pipes-metric-keys-dropdown',
866
+ options=(
867
+ sorted(list({pipe.metric_key for pipe in pipes}))
868
+ if not mk_alone
869
+ else sorted(list({mk for _, mk, _ in all_keys}))
870
+ ),
871
+ value=[str(mk) for mk in metric_keys],
872
+ placeholder='Metrics',
873
+ multi=True,
874
+ ),
875
+ ],
876
+ className='dbc_dark'
877
+ ),
878
+ lg=4,
879
+ md=12,
880
+ sm=12,
881
+ ),
882
+ dbc.Col(
883
+ html.Div(
884
+ [
885
+ dcc.Dropdown(
886
+ id='pipes-location-keys-dropdown',
887
+ options=(
888
+ sorted(list({str(pipe.location_key) for pipe in pipes}))
889
+ if not lk_alone
890
+ else sorted(list({str(lk) for _, _, lk in all_keys}))
891
+ ),
892
+ value=[str(lk) for lk in location_keys],
893
+ placeholder='Locations',
894
+ multi=True,
895
+ ),
896
+ ],
897
+ className='dbc_dark'
898
+ ),
899
+ lg=4,
900
+ md=12,
901
+ sm=12,
902
+ ),
903
+ ] ### end of filters row children
904
+ )
905
+
906
+
907
+ def build_pipes_tags_dropdown(
908
+ connector_keys: List[str],
909
+ metric_keys: List[str],
910
+ location_keys: List[str],
911
+ tags: List[str],
912
+ instance: str,
913
+ ) -> html.Div:
914
+ """
915
+ Build the tags dropdown for the dedicated pipes page.
916
+ """
917
+ _tags_alone = tags and not any([str(x) for x in (connector_keys + metric_keys + location_keys)])
918
+ _tags_pipes = mrsm.get_pipes(
919
+ connector_keys=connector_keys,
920
+ metric_keys=metric_keys,
921
+ location_keys=location_keys,
922
+ tags=tags,
923
+ instance=instance,
924
+ as_tags_dict=True,
925
+ )
926
+
927
+ _all_tags = list(
928
+ mrsm.get_pipes(
929
+ instance=instance,
930
+ as_tags_dict=True,
931
+ )
932
+ ) if _tags_alone else []
933
+
934
+ tags_options = [
935
+ str(tag)
936
+ for tag in (_all_tags if _tags_alone else _tags_pipes)
937
+ ]
938
+
939
+ return html.Div(
940
+ dcc.Dropdown(
941
+ id='pipes-tags-dropdown',
942
+ options=tags_options,
943
+ value=tags,
944
+ placeholder='Tags',
945
+ multi=True,
946
+ searchable=True,
947
+ ),
948
+ className="dbc_dark",
949
+ id="pipes-tags-dropdown-div",
950
+ )
@@ -9,7 +9,7 @@ Dash utility functions for constructing tokens components.
9
9
  from __future__ import annotations
10
10
 
11
11
  from datetime import datetime, timezone, timedelta
12
- from typing import Any, List
12
+ from typing import Any, List, Optional
13
13
 
14
14
  import meerschaum as mrsm
15
15
  from meerschaum.api import debug, CHECK_UPDATE, get_api_connector
@@ -18,8 +18,8 @@ from meerschaum.api.dash.components import alert_from_success_tuple
18
18
  from meerschaum.api.dash.sessions import get_user_from_session
19
19
  from meerschaum.utils.typing import WebState, SuccessTuple, List, Tuple
20
20
  from meerschaum.utils.packages import attempt_import, import_html, import_dcc
21
- from meerschaum.utils.misc import interval_str, round_time
22
- from meerschaum.utils.dtypes import value_is_null
21
+ from meerschaum.utils.misc import interval_str
22
+ from meerschaum.utils.dtypes import value_is_null, round_time
23
23
  from meerschaum._internal.static import STATIC_CONFIG
24
24
  from meerschaum.core import Token
25
25
  from meerschaum.utils.daemon import get_new_daemon_name
@@ -91,39 +91,36 @@ def build_manage_token_popover(token: Token) -> dbc.Popover:
91
91
  """
92
92
  return dbc.Popover(
93
93
  [
94
- dbc.PopoverHeader(["Manage token"]),
95
- dbc.PopoverBody([
96
- dbc.ButtonGroup(
97
- ([
98
- dbc.Button(
99
- "Edit",
100
- outline=True,
101
- color='light',
102
- id={
103
- 'type': 'tokens-edit-button',
104
- 'index': str(token.id),
105
- },
106
- ),
107
- dbc.Button(
108
- "Invalidate",
109
- outline=True,
110
- color='warning',
111
- id={
112
- 'type': 'tokens-invalidate-button',
113
- 'index': str(token.id),
114
- },
115
- ),
116
- ] if token.is_valid else []) + [
94
+ dbc.ButtonGroup(
95
+ ([
117
96
  dbc.Button(
118
- "Delete",
119
- color='danger',
97
+ "Edit",
120
98
  outline=True,
99
+ color='light',
121
100
  id={
122
- 'type': 'tokens-delete-button',
101
+ 'type': 'tokens-edit-button',
123
102
  'index': str(token.id),
124
103
  },
125
104
  ),
126
- ]),
105
+ dbc.Button(
106
+ "Invalidate",
107
+ outline=True,
108
+ color='warning',
109
+ id={
110
+ 'type': 'tokens-invalidate-button',
111
+ 'index': str(token.id),
112
+ },
113
+ ),
114
+ ] if token.is_valid else []) + [
115
+ dbc.Button(
116
+ "Delete",
117
+ color='danger',
118
+ outline=True,
119
+ id={
120
+ 'type': 'tokens-delete-button',
121
+ 'index': str(token.id),
122
+ },
123
+ ),
127
124
  ]),
128
125
  ],
129
126
  body=True,
@@ -600,7 +597,7 @@ def build_tokens_register_output_modal(token: Token) -> List[Any]:
600
597
  dbc.Button(
601
598
  "Close",
602
599
  id='tokens-close-register-output-modal-button',
603
- disabled=True,
600
+ disabled=success,
604
601
  ),
605
602
  ]),
606
603
  ]
@@ -23,9 +23,7 @@ from meerschaum.api import (
23
23
  pipes,
24
24
  get_pipe,
25
25
  _get_pipes,
26
- manager,
27
26
  debug,
28
- no_auth,
29
27
  ScopedAuth,
30
28
  )
31
29
  from meerschaum.models import (
@@ -74,7 +72,7 @@ def register_pipe(
74
72
  instance_keys: Optional[str] = None,
75
73
  parameters: Optional[Dict[str, Any]] = None,
76
74
  curr_user = fastapi.Security(ScopedAuth(['pipes:write']), scopes=['pipes:write']),
77
- ) -> SuccessTupleResponseModel:
75
+ ) -> mrsm.SuccessTuple:
78
76
  """
79
77
  Register a new pipe.
80
78
  """
@@ -94,8 +92,9 @@ def register_pipe(
94
92
  )
95
93
  if parameters:
96
94
  pipe.parameters = parameters
95
+
97
96
  success, msg = get_api_connector(instance_keys).register_pipe(pipe, debug=debug)
98
- pipes(instance_keys, refresh=True)
97
+ _ = pipes(instance_keys, refresh=True)
99
98
  return success, msg
100
99
 
101
100
 
@@ -112,7 +111,7 @@ def edit_pipe(
112
111
  instance_keys: Optional[str] = None,
113
112
  patch: bool = False,
114
113
  curr_user = fastapi.Security(ScopedAuth(['pipes:write'])),
115
- ) -> SuccessTupleResponseModel:
114
+ ) -> mrsm.SuccessTuple:
116
115
  """
117
116
  Edit an existing pipe's parameters.
118
117
  """
@@ -125,14 +124,16 @@ def edit_pipe(
125
124
  " Under the keys `api:permissions:actions`, "
126
125
  "you can toggle non-admin actions."
127
126
  )
127
+
128
128
  pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
129
129
  if not is_pipe_registered(pipe, pipes(instance_keys, refresh=True)):
130
130
  raise fastapi.HTTPException(
131
131
  status_code=409, detail=f"{pipe} is not registered."
132
132
  )
133
+
133
134
  pipe.parameters = parameters
134
135
  success, msg = get_api_connector(instance_keys).edit_pipe(pipe, patch=patch, debug=debug)
135
- pipes(instance_keys, refresh=True)
136
+ _ = pipes(instance_keys, refresh=True)
136
137
  return success, msg
137
138
 
138
139
 
@@ -147,7 +148,7 @@ def delete_pipe(
147
148
  location_key: str,
148
149
  instance_keys: Optional[str] = None,
149
150
  curr_user = fastapi.Security(ScopedAuth(['pipes:delete'])),
150
- ) -> SuccessTupleResponseModel:
151
+ ) -> SuccessTuple:
151
152
  """
152
153
  Delete a Pipe (without dropping its table).
153
154
  """
@@ -156,9 +157,10 @@ def delete_pipe(
156
157
  raise fastapi.HTTPException(
157
158
  status_code=409, detail=f"{pipe} is not registered."
158
159
  )
159
- results = get_api_connector(instance_keys).delete_pipe(pipe, debug=debug)
160
- pipes(instance_keys, refresh=True)
161
- return results
160
+
161
+ success, msg = get_api_connector(instance_keys).delete_pipe(pipe, debug=debug)
162
+ _ = pipes(instance_keys, refresh=True)
163
+ return success, msg
162
164
 
163
165
 
164
166
  @app.get(
@@ -207,6 +209,7 @@ async def get_pipes(
207
209
  kw['metric_keys'] = metric_keys
208
210
  if location_keys != "":
209
211
  kw['location_keys'] = location_keys
212
+
210
213
  pipes_dict = replace_pipes_in_dict(_get_pipes(**kw), lambda p: p.attributes)
211
214
  for metrics in pipes_dict.values():
212
215
  for locations in metrics.values():
@@ -224,14 +227,19 @@ async def get_pipes_by_connector(
224
227
  """
225
228
  Get all registered Pipes by connector_keys with metadata, excluding parameters.
226
229
  """
227
- if connector_keys not in pipes(instance_keys):
230
+ if connector_keys not in pipes(instance_keys, refresh=True):
228
231
  raise fastapi.HTTPException(
229
232
  status_code=404, detail=f"Connector '{connector_keys}' not found."
230
233
  )
231
- metrics = replace_pipes_in_dict(pipes(instance_keys)[connector_keys], lambda p: p.attributes)
234
+
235
+ metrics = replace_pipes_in_dict(
236
+ pipes(instance_keys, refresh=False)[connector_keys],
237
+ lambda p: p.attributes
238
+ )
232
239
  for locations in metrics.values():
233
240
  if None in locations:
234
241
  locations['None'] = locations.pop(None)
242
+
235
243
  return metrics
236
244
 
237
245
 
@@ -245,22 +253,26 @@ async def get_pipes_by_connector_and_metric(
245
253
  """
246
254
  Get all registered Pipes by `connector_keys` and `metric_key` with metadata, excluding parameters.
247
255
  """
248
- if connector_keys not in pipes(instance_keys):
256
+ if connector_keys not in pipes(instance_keys, refresh=True):
249
257
  raise fastapi.HTTPException(
250
258
  status_code=404,
251
259
  detail=f"Connector '{connector_keys}' not found.",
252
260
  )
253
- if metric_key not in pipes(instance_keys)[connector_keys]:
261
+
262
+ if metric_key not in pipes(instance_keys, refresh=False)[connector_keys]:
254
263
  raise fastapi.HTTPException(
255
264
  status_code=404,
256
265
  detail=f"Metric '{metric_key}' not found.",
257
266
  )
267
+
258
268
  locations = replace_pipes_in_dict(
259
- pipes(instance_keys)[connector_keys][metric_key],
269
+ pipes(instance_keys, refresh=False)[connector_keys][metric_key],
260
270
  lambda p: p.attributes
261
271
  )
272
+
262
273
  if None in locations:
263
274
  locations['None'] = locations.pop(None)
275
+
264
276
  return locations
265
277
 
266
278
 
@@ -278,22 +290,25 @@ async def get_pipe_by_connector_and_metric_and_location(
278
290
  """
279
291
  Get a specific Pipe with metadata, excluding parameters.
280
292
  """
281
- if connector_keys not in pipes(instance_keys):
293
+ if connector_keys not in pipes(instance_keys, refresh=True):
282
294
  raise fastapi.HTTPException(
283
295
  status_code=404,
284
296
  detail=f"Connector '{connector_keys}' not found.",
285
297
  )
286
- if metric_key not in pipes(instance_keys)[connector_keys]:
298
+
299
+ if metric_key not in pipes(instance_keys, refresh=False)[connector_keys]:
287
300
  raise fastapi.HTTPException(status_code=404, detail=f"Metric '{metric_key}' not found.")
301
+
288
302
  if location_key in ('[None]', 'None', 'null'):
289
303
  location_key = None
290
- if location_key not in pipes(instance_keys)[connector_keys][metric_key]:
304
+
305
+ if location_key not in pipes(instance_keys, refresh=False)[connector_keys][metric_key]:
291
306
  raise fastapi.HTTPException(
292
307
  status_code=404,
293
308
  detail=f"location_key '{location_key}' not found."
294
309
  )
295
310
 
296
- return pipes(instance_keys)[connector_keys][metric_key][location_key].attributes
311
+ return pipes(instance_keys, refresh=False)[connector_keys][metric_key][location_key].attributes
297
312
 
298
313
 
299
314
  @app.get(
@@ -397,7 +412,7 @@ async def sync_pipe(
397
412
  detail="Cannot sync given data.",
398
413
  )
399
414
 
400
- pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
415
+ pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys, refresh=True)
401
416
  if pipe.target in ('mrsm_users', 'mrsm_plugins', 'mrsm_pipes', 'mrsm_tokens'):
402
417
  raise fastapi.HTTPException(
403
418
  status_code=409,
@@ -616,23 +631,14 @@ def drop_pipe(
616
631
  location_key: str,
617
632
  instance_keys: Optional[str] = None,
618
633
  curr_user = fastapi.Security(ScopedAuth(['pipes:drop'])),
619
- ) -> SuccessTupleResponseModel:
634
+ ) -> mrsm.SuccessTuple:
620
635
  """
621
636
  Drop a pipe's target table.
622
637
  """
623
- allow_actions = mrsm.get_config('system', 'api', 'permissions', 'actions', 'non_admin')
624
- if not allow_actions:
625
- return False, (
626
- "The administrator for this server has not allowed actions.\n\n"
627
- "Please contact the system administrator, or if you are running this server, "
628
- "open the configuration file with `edit config system` and search for 'permissions'."
629
- " Under the keys `api:permissions:actions`, " +
630
- "you can toggle non-admin actions."
631
- )
632
- pipe_object = get_pipe(connector_keys, metric_key, location_key, instance_keys)
633
- results = get_api_connector(instance_keys=instance_keys).drop_pipe(pipe_object, debug=debug)
634
- pipes(instance_keys, refresh=True)
635
- return results
638
+ pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
639
+ success, msg = pipe.drop(debug=debug)
640
+ _ = pipes(instance_keys, refresh=True)
641
+ return success, msg
636
642
 
637
643
 
638
644
  @app.delete(
@@ -661,6 +667,7 @@ def clear_pipe(
661
667
  _params = json.loads(params)
662
668
  except Exception:
663
669
  _params = None
670
+
664
671
  if not isinstance(_params, dict):
665
672
  raise fastapi.HTTPException(
666
673
  status_code=409,
@@ -676,7 +683,7 @@ def clear_pipe(
676
683
  params=_params,
677
684
  debug=debug,
678
685
  )
679
- pipes(instance_keys, refresh=True)
686
+ _ = pipes(instance_keys, refresh=True)
680
687
  return results
681
688
 
682
689
 
@@ -894,8 +901,11 @@ def get_pipe_columns_types(
894
901
  ```
895
902
  """
896
903
  pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
897
- columns_types = pipe.get_columns_types(debug=debug)
898
- return pipe.dtypes
904
+ columns_types = (
905
+ pipe.get_columns_types(debug=debug)
906
+ or pipe.get_dtypes(refresh=True, debug=debug)
907
+ )
908
+ return columns_types
899
909
 
900
910
 
901
911
  @app.get(
@@ -99,6 +99,7 @@ default_system_config = {
99
99
  'mssql': True,
100
100
  },
101
101
  'instance': {
102
+ 'create_metadata_cache_minutes': 14400,
102
103
  'stale_temporary_tables_minutes': 1440,
103
104
  'temporary_target': {
104
105
  'prefix': '_',
@@ -199,14 +200,25 @@ default_pipes_config = {
199
200
  },
200
201
  },
201
202
  'attributes': {
202
- 'local_cache_timeout_seconds': 60,
203
+ 'local_cache_timeout_seconds': 600.0,
203
204
  },
204
205
  'sync': {
205
206
  'filter_params_index_limit': 250,
207
+ 'exists_cache_seconds': 60.0,
206
208
  },
207
209
  'verify': {
208
210
  'max_chunks_syncs': 3,
209
211
  },
212
+ 'autotime': {
213
+ 'column_name_if_datetime_missing': 'ts',
214
+ },
215
+ 'dtypes': {
216
+ 'min_ratio_columns_changed_for_full_astype': 0.5,
217
+ 'columns_types_cache_seconds': 60.0,
218
+ },
219
+ 'static': {
220
+ 'static_schema_cache_seconds': 3600.0,
221
+ },
210
222
  }
211
223
  default_plugins_config = {}
212
224
  default_experimental_config = {
@@ -214,7 +226,6 @@ default_experimental_config = {
214
226
  }
215
227
 
216
228
 
217
-
218
229
  ### build default config dictionary
219
230
  default_config = {}
220
231
  default_config['meerschaum'] = default_meerschaum_config
@@ -149,6 +149,7 @@ paths = {
149
149
  'PIPES_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'pipes'),
150
150
  'USERS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'users'),
151
151
  'VENVS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'venvs'),
152
+ 'SQL_CONN_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'sql'),
152
153
 
153
154
  'PLUGINS_RESOURCES_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins'),
154
155
  'PLUGINS_INTERNAL_LOCK_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins.lock'),
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "3.0.0rc1"
5
+ __version__ = "3.0.0rc3"
@@ -122,9 +122,9 @@ default_docker_compose_config = {
122
122
  'POSTGRES_DB': '<DOLLAR>POSTGRES_DB',
123
123
  'POSTGRES_PASSWORD': '<DOLLAR>POSTGRES_PASSWORD',
124
124
  'ALLOW_IP_RANGE': env_dict['ALLOW_IP_RANGE'],
125
- 'POSTGRES_INITDB_ARGS': '-c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100'
125
+ # 'POSTGRES_INITDB_ARGS': '-c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100'
126
126
  },
127
- # 'command': 'postgres -c max_connections=1000 -c shared_buffers=1024MB',
127
+ 'command': 'postgres -c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100',
128
128
  'healthcheck': {
129
129
  'test': [
130
130
  'CMD-SHELL', 'pg_isready -d <DOLLAR>POSTGRES_DB -U <DOLLAR>POSTGRES_USER',
@@ -305,19 +305,20 @@ def get_necessary_files():
305
305
 
306
306
 
307
307
  def write_stack(
308
- debug: bool = False
309
- ):
308
+ debug: bool = False
309
+ ):
310
310
  """Write Docker Compose configuration files."""
311
311
  from meerschaum.config._edit import general_write_yaml_config
312
312
  from meerschaum.config._sync import sync_files
313
313
  general_write_yaml_config(get_necessary_files(), debug=debug)
314
314
  return sync_files(['stack'])
315
315
 
316
+
316
317
  def edit_stack(
317
- action: Optional[List[str]] = None,
318
- debug: bool = False,
319
- **kw
320
- ):
318
+ action: Optional[List[str]] = None,
319
+ debug: bool = False,
320
+ **kw
321
+ ):
321
322
  """Open docker-compose.yaml or .env for editing."""
322
323
  from meerschaum.config._edit import general_edit_config
323
324
  if action is None: