meerschaum 2.9.5__py3-none-any.whl → 3.0.0rc2__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 (158) hide show
  1. meerschaum/__init__.py +5 -2
  2. meerschaum/_internal/__init__.py +1 -0
  3. meerschaum/_internal/arguments/_parse_arguments.py +4 -4
  4. meerschaum/_internal/arguments/_parser.py +19 -2
  5. meerschaum/_internal/docs/index.py +49 -2
  6. meerschaum/_internal/entry.py +6 -6
  7. meerschaum/_internal/shell/Shell.py +1 -1
  8. meerschaum/_internal/static.py +356 -0
  9. meerschaum/actions/api.py +12 -2
  10. meerschaum/actions/bootstrap.py +7 -7
  11. meerschaum/actions/edit.py +142 -18
  12. meerschaum/actions/register.py +137 -6
  13. meerschaum/actions/show.py +117 -29
  14. meerschaum/actions/stop.py +4 -1
  15. meerschaum/actions/sync.py +1 -1
  16. meerschaum/actions/tag.py +9 -8
  17. meerschaum/actions/verify.py +5 -8
  18. meerschaum/api/__init__.py +11 -3
  19. meerschaum/api/_events.py +39 -2
  20. meerschaum/api/_oauth2.py +118 -8
  21. meerschaum/api/_tokens.py +102 -0
  22. meerschaum/api/dash/__init__.py +0 -3
  23. meerschaum/api/dash/callbacks/custom.py +2 -2
  24. meerschaum/api/dash/callbacks/dashboard.py +103 -19
  25. meerschaum/api/dash/callbacks/plugins.py +0 -1
  26. meerschaum/api/dash/callbacks/register.py +1 -1
  27. meerschaum/api/dash/callbacks/settings/__init__.py +1 -0
  28. meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
  29. meerschaum/api/dash/callbacks/settings/tokens.py +388 -0
  30. meerschaum/api/dash/components.py +30 -8
  31. meerschaum/api/dash/keys.py +19 -93
  32. meerschaum/api/dash/pages/dashboard.py +1 -20
  33. meerschaum/api/dash/pages/settings/__init__.py +1 -0
  34. meerschaum/api/dash/pages/settings/password_reset.py +1 -1
  35. meerschaum/api/dash/pages/settings/tokens.py +55 -0
  36. meerschaum/api/dash/pipes.py +94 -59
  37. meerschaum/api/dash/sessions.py +12 -0
  38. meerschaum/api/dash/tokens.py +606 -0
  39. meerschaum/api/dash/websockets.py +1 -1
  40. meerschaum/api/dash/webterm.py +4 -0
  41. meerschaum/api/models/__init__.py +23 -3
  42. meerschaum/api/models/_actions.py +22 -0
  43. meerschaum/api/models/_pipes.py +85 -7
  44. meerschaum/api/models/_tokens.py +81 -0
  45. meerschaum/api/resources/templates/termpage.html +12 -0
  46. meerschaum/api/routes/__init__.py +1 -0
  47. meerschaum/api/routes/_actions.py +3 -4
  48. meerschaum/api/routes/_connectors.py +3 -7
  49. meerschaum/api/routes/_jobs.py +14 -35
  50. meerschaum/api/routes/_login.py +49 -12
  51. meerschaum/api/routes/_misc.py +5 -10
  52. meerschaum/api/routes/_pipes.py +173 -140
  53. meerschaum/api/routes/_plugins.py +38 -28
  54. meerschaum/api/routes/_tokens.py +236 -0
  55. meerschaum/api/routes/_users.py +47 -35
  56. meerschaum/api/routes/_version.py +3 -3
  57. meerschaum/config/__init__.py +43 -20
  58. meerschaum/config/_default.py +43 -6
  59. meerschaum/config/_edit.py +28 -24
  60. meerschaum/config/_environment.py +1 -1
  61. meerschaum/config/_patch.py +6 -6
  62. meerschaum/config/_paths.py +5 -1
  63. meerschaum/config/_read_config.py +65 -34
  64. meerschaum/config/_sync.py +6 -3
  65. meerschaum/config/_version.py +1 -1
  66. meerschaum/config/stack/__init__.py +31 -11
  67. meerschaum/config/static.py +18 -0
  68. meerschaum/connectors/_Connector.py +10 -4
  69. meerschaum/connectors/__init__.py +4 -20
  70. meerschaum/connectors/api/_APIConnector.py +34 -6
  71. meerschaum/connectors/api/_actions.py +2 -2
  72. meerschaum/connectors/api/_jobs.py +1 -1
  73. meerschaum/connectors/api/_login.py +33 -7
  74. meerschaum/connectors/api/_misc.py +2 -2
  75. meerschaum/connectors/api/_pipes.py +16 -31
  76. meerschaum/connectors/api/_plugins.py +2 -2
  77. meerschaum/connectors/api/_request.py +1 -1
  78. meerschaum/connectors/api/_tokens.py +146 -0
  79. meerschaum/connectors/api/_users.py +70 -58
  80. meerschaum/connectors/instance/_InstanceConnector.py +83 -0
  81. meerschaum/connectors/instance/__init__.py +10 -0
  82. meerschaum/connectors/instance/_pipes.py +442 -0
  83. meerschaum/connectors/instance/_plugins.py +151 -0
  84. meerschaum/connectors/instance/_tokens.py +296 -0
  85. meerschaum/connectors/instance/_users.py +181 -0
  86. meerschaum/connectors/parse.py +4 -1
  87. meerschaum/connectors/sql/_SQLConnector.py +8 -5
  88. meerschaum/connectors/sql/_cli.py +12 -11
  89. meerschaum/connectors/sql/_create_engine.py +9 -168
  90. meerschaum/connectors/sql/_fetch.py +2 -18
  91. meerschaum/connectors/sql/_pipes.py +156 -190
  92. meerschaum/connectors/sql/_plugins.py +29 -0
  93. meerschaum/connectors/sql/_sql.py +46 -21
  94. meerschaum/connectors/sql/_users.py +29 -2
  95. meerschaum/connectors/sql/tables/__init__.py +1 -1
  96. meerschaum/connectors/valkey/_ValkeyConnector.py +2 -4
  97. meerschaum/connectors/valkey/_pipes.py +53 -26
  98. meerschaum/connectors/valkey/_plugins.py +2 -26
  99. meerschaum/core/Pipe/__init__.py +59 -19
  100. meerschaum/core/Pipe/_attributes.py +412 -90
  101. meerschaum/core/Pipe/_bootstrap.py +54 -24
  102. meerschaum/core/Pipe/_data.py +96 -18
  103. meerschaum/core/Pipe/_dtypes.py +48 -18
  104. meerschaum/core/Pipe/_edit.py +14 -4
  105. meerschaum/core/Pipe/_fetch.py +1 -1
  106. meerschaum/core/Pipe/_show.py +5 -5
  107. meerschaum/core/Pipe/_sync.py +118 -193
  108. meerschaum/core/Pipe/_verify.py +4 -4
  109. meerschaum/{plugins → core/Plugin}/_Plugin.py +9 -11
  110. meerschaum/core/Plugin/__init__.py +1 -1
  111. meerschaum/core/Token/_Token.py +220 -0
  112. meerschaum/core/Token/__init__.py +12 -0
  113. meerschaum/core/User/_User.py +34 -8
  114. meerschaum/core/User/__init__.py +9 -1
  115. meerschaum/core/__init__.py +1 -0
  116. meerschaum/jobs/_Job.py +3 -2
  117. meerschaum/jobs/__init__.py +3 -2
  118. meerschaum/jobs/systemd.py +1 -1
  119. meerschaum/models/__init__.py +35 -0
  120. meerschaum/models/pipes.py +247 -0
  121. meerschaum/models/tokens.py +38 -0
  122. meerschaum/models/users.py +26 -0
  123. meerschaum/plugins/__init__.py +22 -7
  124. meerschaum/plugins/bootstrap.py +2 -1
  125. meerschaum/utils/_get_pipes.py +68 -27
  126. meerschaum/utils/daemon/Daemon.py +2 -1
  127. meerschaum/utils/daemon/__init__.py +30 -2
  128. meerschaum/utils/dataframe.py +473 -81
  129. meerschaum/utils/debug.py +15 -15
  130. meerschaum/utils/dtypes/__init__.py +473 -34
  131. meerschaum/utils/dtypes/sql.py +368 -28
  132. meerschaum/utils/formatting/__init__.py +1 -1
  133. meerschaum/utils/formatting/_pipes.py +5 -4
  134. meerschaum/utils/formatting/_shell.py +11 -9
  135. meerschaum/utils/misc.py +246 -148
  136. meerschaum/utils/packages/__init__.py +10 -27
  137. meerschaum/utils/packages/_packages.py +41 -34
  138. meerschaum/utils/pipes.py +181 -0
  139. meerschaum/utils/process.py +1 -1
  140. meerschaum/utils/prompt.py +3 -1
  141. meerschaum/utils/schedule.py +2 -1
  142. meerschaum/utils/sql.py +121 -44
  143. meerschaum/utils/typing.py +1 -4
  144. meerschaum/utils/venv/_Venv.py +2 -2
  145. meerschaum/utils/venv/__init__.py +5 -7
  146. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/METADATA +92 -96
  147. meerschaum-3.0.0rc2.dist-info/RECORD +283 -0
  148. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/WHEEL +1 -1
  149. meerschaum-3.0.0rc2.dist-info/licenses/NOTICE +2 -0
  150. meerschaum/api/models/_interfaces.py +0 -15
  151. meerschaum/api/models/_locations.py +0 -15
  152. meerschaum/api/models/_metrics.py +0 -15
  153. meerschaum/config/static/__init__.py +0 -186
  154. meerschaum-2.9.5.dist-info/RECORD +0 -263
  155. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/entry_points.txt +0 -0
  156. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/licenses/LICENSE +0 -0
  157. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/top_level.txt +0 -0
  158. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc2.dist-info}/zip-safe +0 -0
@@ -18,7 +18,7 @@ from meerschaum.utils.packages import attempt_import, import_dcc, import_html, i
18
18
  from meerschaum.utils.sql import get_pd_type
19
19
  from meerschaum.utils.yaml import yaml
20
20
  from meerschaum.utils.warnings import warn
21
- from meerschaum.utils.dataframe import to_json
21
+ from meerschaum.utils.dataframe import to_json, to_simple_lines
22
22
  from meerschaum.connectors.sql._fetch import get_pipe_query
23
23
  from meerschaum.api import CHECK_UPDATE
24
24
  from meerschaum.api.dash import debug, _get_pipes
@@ -58,28 +58,20 @@ def pipe_from_ctx(ctx, trigger_property: str = 'n_clicks') -> Union[mrsm.Pipe, N
58
58
 
59
59
  def keys_from_state(
60
60
  state: Dict[str, Any],
61
- with_params: bool = False
61
+ with_tags: bool = False,
62
62
  ) -> Union[
63
63
  Tuple[List[str], List[str], List[str]],
64
- Tuple[List[str], List[str], List[str], str],
64
+ Tuple[List[str], List[str], List[str], List[str]],
65
65
  ]:
66
66
  """
67
67
  Read the current state and return the selected keys lists.
68
68
  """
69
69
  _filters = {
70
- 'ck' : state.get(f"connector-keys-{state['pipes-filter-tabs.active_tab']}.value", None),
71
- 'mk' : state.get(f"metric-keys-{state['pipes-filter-tabs.active_tab']}.value", None),
72
- 'lk' : state.get(f"location-keys-{state['pipes-filter-tabs.active_tab']}.value", None),
70
+ 'ck': state.get("connector-keys-dropdown.value", None),
71
+ 'mk': state.get("metric-keys-dropdown.value", None),
72
+ 'lk': state.get("location-keys-dropdown.value", None),
73
+ 'tags': state.get("tags-dropdown.value", None),
73
74
  }
74
- if state['pipes-filter-tabs.active_tab'] == 'input':
75
- try:
76
- # params = string_to_dict(state['params-textarea.value'])
77
- params = string_to_dict(state['search-parameters-editor.value'])
78
- except Exception:
79
- params = None
80
- else:
81
- params = None
82
-
83
75
  for k in _filters:
84
76
  _filters[k] = [] if _filters[k] is None else _filters[k]
85
77
  if not isinstance(_filters[k], list):
@@ -89,8 +81,8 @@ def keys_from_state(
89
81
  print(e)
90
82
  _filters[k] = []
91
83
  keys = [_filters['ck'], _filters['mk'], _filters['lk']]
92
- if with_params:
93
- keys.append(params)
84
+ if with_tags:
85
+ keys.append(_filters['tags'])
94
86
  return tuple(keys)
95
87
 
96
88
 
@@ -98,12 +90,12 @@ def pipes_from_state(
98
90
  state: Dict[str, Any],
99
91
  **kw
100
92
  ):
101
- _ck, _mk, _lk, _params = keys_from_state(state, with_params=True)
93
+ _ck, _mk, _lk, _tags = keys_from_state(state, with_tags=True)
102
94
  try:
103
95
  _pipes = _get_pipes(
104
96
  _ck, _mk, _lk,
105
- params = _params,
106
- mrsm_instance = get_web_connector(state),
97
+ tags=(_tags or []),
98
+ mrsm_instance=get_web_connector(state),
107
99
  **kw
108
100
  )
109
101
  except Exception as e:
@@ -466,7 +458,7 @@ def accordion_items_from_pipe(
466
458
  overview_rows.append(
467
459
  html.Tr([
468
460
  html.Td("Indices" if len(indices_rows) != 1 else "Index"),
469
- html.Td(indices_table),
461
+ html.Td(html.Div(indices_table, style={'overflowX': 'auto'})),
470
462
  ])
471
463
  )
472
464
 
@@ -536,9 +528,9 @@ def accordion_items_from_pipe(
536
528
  ]
537
529
  columns_body = [html.Tbody(columns_rows)]
538
530
  columns_table = dbc.Table(columns_header + columns_body, bordered=False, hover=True)
531
+ items_bodies['columns'] = html.Div(columns_table, style={'overflowX': 'auto'})
539
532
  except Exception:
540
- columns_table = html.P("Could not retrieve columns ― please try again.")
541
- items_bodies['columns'] = columns_table
533
+ items_bodies['columns'] = html.P("Could not retrieve columns ― please try again.")
542
534
 
543
535
  if 'parameters' in active_items:
544
536
  parameters_editor = dash_ace.DashAceEditor(
@@ -579,21 +571,28 @@ def accordion_items_from_pipe(
579
571
  parameters_editor,
580
572
  html.Br(),
581
573
  dbc.Row([
582
- dbc.Col(html.Span(
583
- (
584
- ([update_parameters_button] if authenticated else []) +
585
- [
586
- as_json_button,
587
- as_yaml_button,
588
- ]
589
- )
590
- ), width=4),
591
- dbc.Col([
592
- html.Div(
593
- id={'type': 'update-parameters-success-div', 'index': json.dumps(pipe.meta)}
594
- )
595
- ],
596
- width=True,
574
+ dbc.Col(
575
+ html.Span(
576
+ (
577
+ ([update_parameters_button] if authenticated else []) +
578
+ [
579
+ as_json_button,
580
+ as_yaml_button,
581
+ ]
582
+ )
583
+ ),
584
+ width=4,
585
+ ),
586
+ dbc.Col(
587
+ [
588
+ html.Div(
589
+ id={
590
+ 'type': 'update-parameters-success-div',
591
+ 'index': json.dumps(pipe.meta),
592
+ }
593
+ )
594
+ ],
595
+ width=True,
597
596
  )
598
597
  ]),
599
598
  ]
@@ -665,10 +664,10 @@ def accordion_items_from_pipe(
665
664
  if 'recent-data' in active_items:
666
665
  try:
667
666
  df = pipe.get_backtrack_data(backtrack_minutes=10, limit=10, debug=debug).astype(str)
668
- table = dbc.Table.from_dataframe(df, bordered=False, hover=True)
667
+ table = dbc.Table.from_dataframe(df, bordered=False, hover=True)
668
+ items_bodies['recent-data'] = html.Div(table, style={'overflowX': 'auto'})
669
669
  except Exception:
670
- table = html.P("Could not retrieve recent data.")
671
- items_bodies['recent-data'] = table
670
+ items_bodies['recent-data'] = html.P("Could not retrieve recent data.")
672
671
 
673
672
  if 'query-data' in active_items:
674
673
  query_editor = dash_ace.DashAceEditor(
@@ -722,7 +721,7 @@ def accordion_items_from_pipe(
722
721
  dbc.Row(
723
722
  [
724
723
  dbc.Col([query_data_button], lg=2, md=3, sm=4, xs=6, width=2),
725
- dbc.Col([begin_end_input_group], lg=3, md=3, sm=4, width=4),
724
+ dbc.Col([begin_end_input_group], lg=6, md=6, sm=4, width=6),
726
725
  dbc.Col(html.Div([limit_input, dbc.FormText("Row Limit")]), lg=2, md=3, sm=4, xs=6, width=2),
727
726
  ],
728
727
  justify="between",
@@ -733,23 +732,9 @@ def accordion_items_from_pipe(
733
732
  ])
734
733
 
735
734
  if 'sync-data' in active_items:
736
- backtrack_df = pipe.get_backtrack_data(debug=debug, limit=1)
737
- try:
738
- json_text = to_json(
739
- backtrack_df,
740
- orient='records',
741
- date_format='iso',
742
- force_ascii=False,
743
- indent=4,
744
- date_unit='us',
745
- ) if backtrack_df is not None else '[]'
746
- except Exception as e:
747
- warn(e)
748
- json_text = '[]'
749
-
750
- json_text = json.dumps(json.loads(json_text), indent=4, separators=(',', ': '))
735
+ backtrack_text = get_backtrack_text(pipe)
751
736
  sync_editor = dash_ace.DashAceEditor(
752
- value = json_text,
737
+ value = backtrack_text,
753
738
  mode = 'norm',
754
739
  tabSize = 4,
755
740
  theme = 'twilight',
@@ -763,6 +748,22 @@ def accordion_items_from_pipe(
763
748
  wrapEnabled = True,
764
749
  style = {'min-height': '120px'},
765
750
  )
751
+
752
+ sync_as_json_button = dbc.Button(
753
+ "JSON",
754
+ id={'type': 'sync-as-json-button', 'index': json.dumps(pipe.meta)},
755
+ color='link',
756
+ size='sm',
757
+ style={'text-decoration': 'none', 'margin-left': '10px'},
758
+ )
759
+ sync_as_lines_button = dbc.Button(
760
+ "Lines",
761
+ id={'type': 'sync-as-lines-button', 'index': json.dumps(pipe.meta)},
762
+ color='link',
763
+ size='sm',
764
+ style={'text-decoration': 'none', 'margin-left': '10px'},
765
+ )
766
+
766
767
  update_sync_button = dbc.Button(
767
768
  "Sync",
768
769
  id = {'type': 'update-sync-button', 'index': json.dumps(pipe.meta)},
@@ -772,7 +773,15 @@ def accordion_items_from_pipe(
772
773
  sync_editor,
773
774
  html.Br(),
774
775
  dbc.Row([
775
- dbc.Col([update_sync_button], width=1),
776
+ dbc.Col(html.Span(
777
+ (
778
+ ([update_sync_button] if authenticated else []) +
779
+ [
780
+ sync_as_json_button,
781
+ sync_as_lines_button,
782
+ ]
783
+ )
784
+ ), width=4),
776
785
  dbc.Col([sync_success_div], width=True),
777
786
  ]),
778
787
  ])
@@ -782,3 +791,29 @@ def accordion_items_from_pipe(
782
791
  for item_id, title in items_titles.items()
783
792
  ]
784
793
 
794
+
795
+ def get_backtrack_text(
796
+ pipe: mrsm.Pipe,
797
+ lines: bool = False,
798
+ limit: int = 5,
799
+ ) -> str:
800
+ """
801
+ Return the backtrack documents as text for the sync editor.
802
+ """
803
+ backtrack_df = pipe.get_backtrack_data(debug=debug, limit=limit)
804
+ if lines:
805
+ return to_simple_lines(backtrack_df)
806
+ try:
807
+ json_text = to_json(
808
+ backtrack_df,
809
+ orient='records',
810
+ date_format='iso',
811
+ force_ascii=False,
812
+ indent=4,
813
+ date_unit='us',
814
+ ) if backtrack_df is not None else '[]'
815
+ except Exception as e:
816
+ warn(e)
817
+ json_text = '[]'
818
+
819
+ return json.dumps(json.loads(json_text), indent=4, separators=(',', ': '))
@@ -86,6 +86,18 @@ def get_username_from_session(session_id: Optional[str]) -> Union[str, None]:
86
86
  return session_data.get('username', None)
87
87
 
88
88
 
89
+ def get_user_from_session(session_id: Optional[str]) -> Union[User, None]:
90
+ """
91
+ Return a `User` from the current session.
92
+ """
93
+ username = get_username_from_session(session_id)
94
+ if username is None:
95
+ return None
96
+
97
+ conn = get_api_connector()
98
+ return User(username, instance=conn)
99
+
100
+
89
101
  def is_session_active(session_id: Union[str, None]) -> bool:
90
102
  """
91
103
  Return whether a given `session_id` has been set.