meerschaum 2.9.4__py3-none-any.whl → 3.0.0rc1__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 (154) 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 +17 -1
  5. meerschaum/_internal/entry.py +6 -6
  6. meerschaum/_internal/shell/Shell.py +1 -1
  7. meerschaum/_internal/static.py +372 -0
  8. meerschaum/actions/api.py +12 -2
  9. meerschaum/actions/bootstrap.py +7 -7
  10. meerschaum/actions/edit.py +142 -18
  11. meerschaum/actions/register.py +137 -6
  12. meerschaum/actions/show.py +117 -29
  13. meerschaum/actions/stop.py +4 -1
  14. meerschaum/actions/sync.py +1 -1
  15. meerschaum/actions/tag.py +9 -8
  16. meerschaum/api/__init__.py +9 -2
  17. meerschaum/api/_events.py +39 -2
  18. meerschaum/api/_oauth2.py +118 -8
  19. meerschaum/api/_tokens.py +102 -0
  20. meerschaum/api/dash/__init__.py +0 -1
  21. meerschaum/api/dash/callbacks/custom.py +2 -2
  22. meerschaum/api/dash/callbacks/dashboard.py +133 -18
  23. meerschaum/api/dash/callbacks/plugins.py +0 -1
  24. meerschaum/api/dash/callbacks/register.py +1 -1
  25. meerschaum/api/dash/callbacks/settings/__init__.py +1 -0
  26. meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
  27. meerschaum/api/dash/callbacks/settings/tokens.py +388 -0
  28. meerschaum/api/dash/components.py +30 -8
  29. meerschaum/api/dash/keys.py +19 -93
  30. meerschaum/api/dash/pages/dashboard.py +1 -20
  31. meerschaum/api/dash/pages/settings/__init__.py +1 -0
  32. meerschaum/api/dash/pages/settings/password_reset.py +1 -1
  33. meerschaum/api/dash/pages/settings/tokens.py +55 -0
  34. meerschaum/api/dash/pipes.py +156 -58
  35. meerschaum/api/dash/sessions.py +12 -0
  36. meerschaum/api/dash/tokens.py +606 -0
  37. meerschaum/api/dash/websockets.py +1 -1
  38. meerschaum/api/dash/webterm.py +4 -0
  39. meerschaum/api/models/__init__.py +23 -3
  40. meerschaum/api/models/_actions.py +22 -0
  41. meerschaum/api/models/_pipes.py +85 -7
  42. meerschaum/api/models/_tokens.py +81 -0
  43. meerschaum/api/resources/static/css/dash.css +16 -0
  44. meerschaum/api/resources/templates/termpage.html +12 -0
  45. meerschaum/api/routes/__init__.py +1 -0
  46. meerschaum/api/routes/_actions.py +3 -4
  47. meerschaum/api/routes/_connectors.py +3 -7
  48. meerschaum/api/routes/_jobs.py +14 -35
  49. meerschaum/api/routes/_login.py +49 -12
  50. meerschaum/api/routes/_misc.py +5 -10
  51. meerschaum/api/routes/_pipes.py +134 -111
  52. meerschaum/api/routes/_plugins.py +38 -28
  53. meerschaum/api/routes/_tokens.py +236 -0
  54. meerschaum/api/routes/_users.py +47 -35
  55. meerschaum/api/routes/_version.py +3 -3
  56. meerschaum/config/__init__.py +43 -20
  57. meerschaum/config/_default.py +32 -5
  58. meerschaum/config/_edit.py +28 -24
  59. meerschaum/config/_environment.py +1 -1
  60. meerschaum/config/_patch.py +6 -6
  61. meerschaum/config/_paths.py +5 -1
  62. meerschaum/config/_read_config.py +65 -34
  63. meerschaum/config/_sync.py +6 -3
  64. meerschaum/config/_version.py +1 -1
  65. meerschaum/config/stack/__init__.py +24 -5
  66. meerschaum/config/static.py +18 -0
  67. meerschaum/connectors/_Connector.py +10 -4
  68. meerschaum/connectors/__init__.py +4 -20
  69. meerschaum/connectors/api/_APIConnector.py +34 -6
  70. meerschaum/connectors/api/_actions.py +2 -2
  71. meerschaum/connectors/api/_jobs.py +1 -1
  72. meerschaum/connectors/api/_login.py +33 -7
  73. meerschaum/connectors/api/_misc.py +2 -2
  74. meerschaum/connectors/api/_pipes.py +15 -14
  75. meerschaum/connectors/api/_plugins.py +2 -2
  76. meerschaum/connectors/api/_request.py +1 -1
  77. meerschaum/connectors/api/_tokens.py +146 -0
  78. meerschaum/connectors/api/_users.py +70 -58
  79. meerschaum/connectors/instance/_InstanceConnector.py +83 -0
  80. meerschaum/connectors/instance/__init__.py +10 -0
  81. meerschaum/connectors/instance/_pipes.py +442 -0
  82. meerschaum/connectors/instance/_plugins.py +151 -0
  83. meerschaum/connectors/instance/_tokens.py +296 -0
  84. meerschaum/connectors/instance/_users.py +181 -0
  85. meerschaum/connectors/parse.py +4 -1
  86. meerschaum/connectors/sql/_SQLConnector.py +8 -5
  87. meerschaum/connectors/sql/_cli.py +12 -11
  88. meerschaum/connectors/sql/_create_engine.py +6 -154
  89. meerschaum/connectors/sql/_fetch.py +2 -18
  90. meerschaum/connectors/sql/_pipes.py +42 -31
  91. meerschaum/connectors/sql/_plugins.py +29 -0
  92. meerschaum/connectors/sql/_sql.py +9 -2
  93. meerschaum/connectors/sql/_users.py +29 -2
  94. meerschaum/connectors/sql/tables/__init__.py +1 -1
  95. meerschaum/connectors/valkey/_ValkeyConnector.py +2 -4
  96. meerschaum/connectors/valkey/_pipes.py +9 -10
  97. meerschaum/connectors/valkey/_plugins.py +2 -26
  98. meerschaum/core/Pipe/__init__.py +31 -14
  99. meerschaum/core/Pipe/_attributes.py +156 -58
  100. meerschaum/core/Pipe/_bootstrap.py +54 -24
  101. meerschaum/core/Pipe/_data.py +41 -1
  102. meerschaum/core/Pipe/_dtypes.py +29 -14
  103. meerschaum/core/Pipe/_edit.py +12 -4
  104. meerschaum/core/Pipe/_show.py +5 -5
  105. meerschaum/core/Pipe/_sync.py +48 -53
  106. meerschaum/core/Pipe/_verify.py +1 -1
  107. meerschaum/{plugins → core/Plugin}/_Plugin.py +9 -11
  108. meerschaum/core/Plugin/__init__.py +1 -1
  109. meerschaum/core/Token/_Token.py +221 -0
  110. meerschaum/core/Token/__init__.py +12 -0
  111. meerschaum/core/User/_User.py +34 -8
  112. meerschaum/core/User/__init__.py +9 -1
  113. meerschaum/core/__init__.py +1 -0
  114. meerschaum/jobs/_Job.py +3 -2
  115. meerschaum/jobs/__init__.py +3 -2
  116. meerschaum/jobs/systemd.py +1 -1
  117. meerschaum/models/__init__.py +35 -0
  118. meerschaum/models/pipes.py +247 -0
  119. meerschaum/models/tokens.py +38 -0
  120. meerschaum/models/users.py +26 -0
  121. meerschaum/plugins/__init__.py +22 -7
  122. meerschaum/plugins/bootstrap.py +2 -1
  123. meerschaum/utils/_get_pipes.py +68 -27
  124. meerschaum/utils/daemon/Daemon.py +2 -1
  125. meerschaum/utils/daemon/__init__.py +30 -2
  126. meerschaum/utils/dataframe.py +96 -15
  127. meerschaum/utils/dtypes/__init__.py +93 -21
  128. meerschaum/utils/dtypes/sql.py +44 -0
  129. meerschaum/utils/formatting/__init__.py +1 -1
  130. meerschaum/utils/formatting/_pipes.py +5 -4
  131. meerschaum/utils/formatting/_shell.py +11 -9
  132. meerschaum/utils/misc.py +237 -80
  133. meerschaum/utils/packages/__init__.py +3 -6
  134. meerschaum/utils/packages/_packages.py +34 -32
  135. meerschaum/utils/pipes.py +181 -0
  136. meerschaum/utils/process.py +1 -1
  137. meerschaum/utils/prompt.py +3 -1
  138. meerschaum/utils/schedule.py +1 -0
  139. meerschaum/utils/sql.py +115 -39
  140. meerschaum/utils/typing.py +1 -4
  141. meerschaum/utils/venv/_Venv.py +2 -2
  142. meerschaum/utils/venv/__init__.py +5 -7
  143. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/METADATA +88 -80
  144. meerschaum-3.0.0rc1.dist-info/RECORD +282 -0
  145. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/WHEEL +1 -1
  146. meerschaum/api/models/_interfaces.py +0 -15
  147. meerschaum/api/models/_locations.py +0 -15
  148. meerschaum/api/models/_metrics.py +0 -15
  149. meerschaum/config/static/__init__.py +0 -186
  150. meerschaum-2.9.4.dist-info/RECORD +0 -263
  151. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/entry_points.txt +0 -0
  152. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/licenses/LICENSE +0 -0
  153. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/top_level.txt +0 -0
  154. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0rc1.dist-info}/zip-safe +0 -0
@@ -109,7 +109,6 @@ def get_data(
109
109
  from meerschaum.utils.packages import attempt_import
110
110
  dd = attempt_import('dask.dataframe') if as_dask else None
111
111
  dask = attempt_import('dask') if as_dask else None
112
- dateutil_parser = attempt_import('dateutil.parser')
113
112
 
114
113
  if select_columns == '*':
115
114
  select_columns = None
@@ -833,3 +832,44 @@ def parse_date_bounds(self, *dt_vals: Union[datetime, int, None]) -> Union[
833
832
  if len(bounds) == 1:
834
833
  return bounds[0]
835
834
  return bounds
835
+
836
+
837
+ def get_doc(self, **kwargs) -> Union[Dict[str, Any], None]:
838
+ """
839
+ Convenience function to return a single row as a dictionary (or `None`) from `Pipe.get_data().
840
+ Keywords arguments are passed to `Pipe.get_data()`.
841
+ """
842
+ from meerschaum.utils.warnings import warn
843
+ kwargs['limit'] = 1
844
+ try:
845
+ result_df = self.get_data(**kwargs)
846
+ if result_df is None or len(result_df) == 0:
847
+ return None
848
+ return result_df.reset_index(drop=True).iloc[0].to_dict()
849
+ except Exception as e:
850
+ warn(f"Failed to read value from {self}:\n{e}", stack=False)
851
+ return None
852
+
853
+ def get_value(
854
+ self,
855
+ column: str,
856
+ params: Optional[Dict[str, Any]] = None,
857
+ **kwargs: Any
858
+ ) -> Any:
859
+ """
860
+ Convenience function to return a single value (or `None`) from `Pipe.get_data()`.
861
+ Keywords arguments are passed to `Pipe.get_data()`.
862
+ """
863
+ from meerschaum.utils.warnings import warn
864
+ kwargs['select_columns'] = [column]
865
+ kwargs['limit'] = 1
866
+ try:
867
+ result_df = self.get_data(params=params, **kwargs)
868
+ if result_df is None or len(result_df) == 0:
869
+ return None
870
+ if column not in result_df.columns:
871
+ raise ValueError(f"Column '{column}' was not included in the result set.")
872
+ return result_df[column][0]
873
+ except Exception as e:
874
+ warn(f"Failed to read value from {self}:\n{e}", stack=False)
875
+ return None
@@ -31,7 +31,11 @@ def enforce_dtypes(
31
31
  import traceback
32
32
  from meerschaum.utils.warnings import warn
33
33
  from meerschaum.utils.debug import dprint
34
- from meerschaum.utils.dataframe import parse_df_datetimes, enforce_dtypes as _enforce_dtypes
34
+ from meerschaum.utils.dataframe import (
35
+ parse_df_datetimes,
36
+ enforce_dtypes as _enforce_dtypes,
37
+ parse_simple_lines,
38
+ )
35
39
  from meerschaum.utils.dtypes import are_dtypes_equal
36
40
  from meerschaum.utils.packages import import_pandas
37
41
  pd = import_pandas(debug=debug)
@@ -45,23 +49,34 @@ def enforce_dtypes(
45
49
 
46
50
  if not self.enforce:
47
51
  enforce = False
52
+
48
53
  pipe_dtypes = self.dtypes if enforce else {}
49
54
 
50
55
  try:
51
56
  if isinstance(df, str):
52
- df = parse_df_datetimes(
53
- pd.read_json(StringIO(df)),
54
- ignore_cols=[
55
- col
56
- for col, dtype in pipe_dtypes.items()
57
- if (not enforce or not are_dtypes_equal(dtype, 'datetime'))
58
- ],
59
- ignore_all=(not enforce),
60
- strip_timezone=(self.tzinfo is None),
61
- chunksize=chunksize,
62
- debug=debug,
63
- )
64
- elif isinstance(df, (dict, list)):
57
+ if df.strip() and df.strip()[0] not in ('{', '['):
58
+ df = parse_df_datetimes(
59
+ parse_simple_lines(df),
60
+ ignore_cols=[
61
+ col
62
+ for col, dtype in pipe_dtypes.items()
63
+ if (not enforce or not are_dtypes_equal(dtype, 'datetime'))
64
+ ],
65
+ )
66
+ else:
67
+ df = parse_df_datetimes(
68
+ pd.read_json(StringIO(df)),
69
+ ignore_cols=[
70
+ col
71
+ for col, dtype in pipe_dtypes.items()
72
+ if (not enforce or not are_dtypes_equal(dtype, 'datetime'))
73
+ ],
74
+ ignore_all=(not enforce),
75
+ strip_timezone=(self.tzinfo is None),
76
+ chunksize=chunksize,
77
+ debug=debug,
78
+ )
79
+ elif isinstance(df, (dict, list, tuple)):
65
80
  df = parse_df_datetimes(
66
81
  df,
67
82
  ignore_cols=[
@@ -3,7 +3,7 @@
3
3
  # vim:fenc=utf-8
4
4
 
5
5
  """
6
- Edit a Pipe's parameters here.
6
+ Edit a Pipe's parameters.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
@@ -47,6 +47,13 @@ def edit(
47
47
  if self.temporary:
48
48
  return False, "Cannot edit pipes created with `temporary=True` (read-only)."
49
49
 
50
+ if hasattr(self, '_symlinks'):
51
+ from meerschaum.utils.misc import get_val_from_dict_path, set_val_in_dict_path
52
+ for path, vals in self._symlinks.items():
53
+ current_val = get_val_from_dict_path(self.parameters, path)
54
+ if current_val == vals['substituted']:
55
+ set_val_in_dict_path(self.parameters, path, vals['original'])
56
+
50
57
  if not interactive:
51
58
  with Venv(get_connector_plugin(self.instance_connector)):
52
59
  return self.instance_connector.edit_pipe(self, patch=patch, debug=debug, **kw)
@@ -65,7 +72,8 @@ def edit(
65
72
  from meerschaum.config import get_config
66
73
  parameters = dict(get_config('pipes', 'parameters', patch=True))
67
74
  from meerschaum.config._patch import apply_patch_to_config
68
- parameters = apply_patch_to_config(parameters, self.parameters)
75
+ raw_parameters = self.attributes.get('parameters', {})
76
+ parameters = apply_patch_to_config(parameters, raw_parameters)
69
77
 
70
78
  ### write parameters to yaml file
71
79
  with open(parameters_path, 'w+') as f:
@@ -194,7 +202,7 @@ def edit_definition(
194
202
  return True, "Success"
195
203
 
196
204
  def _edit_sql():
197
- import pathlib, os, textwrap
205
+ import textwrap
198
206
  from meerschaum.config._paths import PIPES_CACHE_RESOURCES_PATH
199
207
  from meerschaum.utils.misc import edit_file
200
208
  definition_filename = str(self) + '.sql'
@@ -214,7 +222,7 @@ def edit_definition(
214
222
 
215
223
  edit_file(definition_path)
216
224
  try:
217
- with open(definition_path, 'r') as f:
225
+ with open(definition_path, 'r', encoding='utf-8') as f:
218
226
  file_definition = f.read()
219
227
  except Exception as e:
220
228
  return False, f"Failed reading file '{definition_path}':\n" + str(e)
@@ -9,11 +9,11 @@ Show information about a Pipe
9
9
  from meerschaum.utils.typing import SuccessTuple
10
10
 
11
11
  def show(
12
- self,
13
- nopretty: bool = False,
14
- debug: bool = False,
15
- **kw
16
- ) -> SuccessTuple:
12
+ self,
13
+ nopretty: bool = False,
14
+ debug: bool = False,
15
+ **kw
16
+ ) -> SuccessTuple:
17
17
  """
18
18
  Show attributes of a Pipe.
19
19
 
@@ -13,7 +13,7 @@ import time
13
13
  import threading
14
14
  import multiprocessing
15
15
  import functools
16
- from datetime import datetime, timedelta
16
+ from datetime import datetime, timedelta, timezone
17
17
  from typing import TYPE_CHECKING
18
18
 
19
19
  import meerschaum as mrsm
@@ -42,6 +42,7 @@ def sync(
42
42
  pd.DataFrame,
43
43
  Dict[str, List[Any]],
44
44
  List[Dict[str, Any]],
45
+ str,
45
46
  InferFetch
46
47
  ] = InferFetch,
47
48
  begin: Union[datetime, int, str, None] = '',
@@ -71,6 +72,7 @@ def sync(
71
72
  ----------
72
73
  df: Union[None, pd.DataFrame, Dict[str, List[Any]]], default None
73
74
  An optional DataFrame to sync into the pipe. Defaults to `None`.
75
+ If `df` is a string, it will be parsed via `meerschaum.utils.dataframe.parse_simple_lines()`.
74
76
 
75
77
  begin: Union[datetime, int, str, None], default ''
76
78
  Optionally specify the earliest datetime to search for data.
@@ -134,6 +136,7 @@ def sync(
134
136
  from meerschaum.utils.misc import df_is_chunk_generator, filter_keywords, filter_arguments
135
137
  from meerschaum.utils.pool import get_pool
136
138
  from meerschaum.config import get_config
139
+ from meerschaum.utils.dtypes import are_dtypes_equal
137
140
 
138
141
  if (callback is not None or error_callback is not None) and blocking:
139
142
  warn("Callback functions are only executed when blocking = False. Ignoring...")
@@ -170,6 +173,7 @@ def sync(
170
173
  'pd.DataFrame',
171
174
  Dict[str, List[Any]],
172
175
  List[Dict[str, Any]],
176
+ str,
173
177
  InferFetch
174
178
  ] = InferFetch,
175
179
  ) -> SuccessTuple:
@@ -189,6 +193,10 @@ def sync(
189
193
  p._exists = None
190
194
  return register_success, register_msg
191
195
 
196
+ if isinstance(df, str):
197
+ from meerschaum.utils.dataframe import parse_simple_lines
198
+ df = parse_simple_lines(df)
199
+
192
200
  ### If connector is a plugin with a `sync()` method, return that instead.
193
201
  ### If the plugin does not have a `sync()` method but does have a `fetch()` method,
194
202
  ### use that instead.
@@ -209,7 +217,7 @@ def sync(
209
217
  p._exists = None
210
218
  return False, f"Unable to create the connector for {p}."
211
219
 
212
- ### Sync in place if this is a SQL pipe.
220
+ ### Sync in place if possible.
213
221
  if (
214
222
  str(self.connector) == str(self.instance_connector)
215
223
  and
@@ -398,6 +406,21 @@ def sync(
398
406
  enforce=enforce_dtypes,
399
407
  debug=debug,
400
408
  )
409
+ if p.autotime:
410
+ dt_col = p.columns.get('datetime', 'ts')
411
+ dt_typ = p.dtypes.get(dt_col, 'datetime') if dt_col else 'datetime'
412
+ if dt_col and hasattr(df, 'columns') and dt_col not in df.columns:
413
+ now = datetime.now(timezone.utc)
414
+ now_val = (
415
+ int(now.timestamp() * 1000)
416
+ if are_dtypes_equal(dt_typ, 'int')
417
+ else now
418
+ )
419
+ if debug:
420
+ dprint(f"Adding current timestamp to dataframe synced to {p}: {now_val}")
421
+
422
+ df[dt_col] = now_val
423
+ kw['check_existing'] = False
401
424
 
402
425
  ### Capture `numeric`, `uuid`, `json`, and `bytes` columns.
403
426
  self._persist_new_json_columns(df, debug=debug)
@@ -447,9 +470,9 @@ def sync(
447
470
  if self.cache_pipe is not None:
448
471
  if debug:
449
472
  dprint("Caching retrieved dataframe.", **kw)
450
- _sync_cache_tuple = self.cache_pipe.sync(df, debug=debug, **kw)
451
- if not _sync_cache_tuple[0]:
452
- warn(f"Failed to sync local cache for {self}.")
473
+ _sync_cache_tuple = self.cache_pipe.sync(df, debug=debug, **kw)
474
+ if not _sync_cache_tuple[0]:
475
+ warn(f"Failed to sync local cache for {self}.")
453
476
 
454
477
  self._exists = None
455
478
  return return_tuple
@@ -691,7 +714,9 @@ def filter_existing(
691
714
  NA = pd.NA
692
715
 
693
716
  primary_key = self.columns.get('primary', None)
717
+ dt_col = self.columns.get('datetime', None)
694
718
  autoincrement = self.parameters.get('autoincrement', False)
719
+ autotime = self.parameters.get('autotime', False)
695
720
  pipe_columns = self.columns.copy()
696
721
 
697
722
  if primary_key and autoincrement and df is not None and primary_key in df.columns:
@@ -702,6 +727,14 @@ def filter_existing(
702
727
  del df[primary_key]
703
728
  _ = self.columns.pop(primary_key, None)
704
729
 
730
+ if dt_col and autotime and df is not None and dt_col in df.columns:
731
+ if safe_copy:
732
+ df = df.copy()
733
+ safe_copy = False
734
+ if df[dt_col].isnull().all():
735
+ del df[dt_col]
736
+ _ = self.columns.pop(dt_col, None)
737
+
705
738
  def get_empty_df():
706
739
  empty_df = pd.DataFrame([])
707
740
  dtypes = dict(df.dtypes) if df is not None else {}
@@ -730,6 +763,11 @@ def filter_existing(
730
763
  df = self.enforce_dtypes(df, chunksize=chunksize, debug=debug)
731
764
  return df, get_empty_df(), df
732
765
 
766
+ if autotime and dt_col and dt_col not in df.columns:
767
+ if enforce_dtypes:
768
+ df = self.enforce_dtypes(df, chunksize=chunksize, debug=debug)
769
+ return df, get_empty_df(), df
770
+
733
771
  try:
734
772
  min_dt_val = df[dt_col].min(skipna=True) if dt_col and dt_col in df.columns else None
735
773
  if is_dask and min_dt_val is not None:
@@ -1013,15 +1051,7 @@ def _persist_new_numeric_columns(self, df, debug: bool = False) -> SuccessTuple:
1013
1051
  self._attributes_sync_time = None
1014
1052
  dtypes = self.parameters.get('dtypes', {})
1015
1053
  dtypes.update({col: 'numeric' for col in new_numeric_cols})
1016
- self.parameters['dtypes'] = dtypes
1017
- if not self.temporary:
1018
- edit_success, edit_msg = self.edit(interactive=False, debug=debug)
1019
- if not edit_success:
1020
- warn(f"Unable to update NUMERIC dtypes for {self}:\n{edit_msg}")
1021
-
1022
- return edit_success, edit_msg
1023
-
1024
- return True, "Success"
1054
+ return self.update_parameters({'dtypes': dtypes}, debug=debug)
1025
1055
 
1026
1056
 
1027
1057
  def _persist_new_uuid_columns(self, df, debug: bool = False) -> SuccessTuple:
@@ -1038,15 +1068,7 @@ def _persist_new_uuid_columns(self, df, debug: bool = False) -> SuccessTuple:
1038
1068
  self._attributes_sync_time = None
1039
1069
  dtypes = self.parameters.get('dtypes', {})
1040
1070
  dtypes.update({col: 'uuid' for col in new_uuid_cols})
1041
- self.parameters['dtypes'] = dtypes
1042
- if not self.temporary:
1043
- edit_success, edit_msg = self.edit(interactive=False, debug=debug)
1044
- if not edit_success:
1045
- warn(f"Unable to update UUID dtypes for {self}:\n{edit_msg}")
1046
-
1047
- return edit_success, edit_msg
1048
-
1049
- return True, "Success"
1071
+ return self.update_parameters({'dtypes': dtypes}, debug=debug)
1050
1072
 
1051
1073
 
1052
1074
  def _persist_new_json_columns(self, df, debug: bool = False) -> SuccessTuple:
@@ -1063,16 +1085,7 @@ def _persist_new_json_columns(self, df, debug: bool = False) -> SuccessTuple:
1063
1085
  self._attributes_sync_time = None
1064
1086
  dtypes = self.parameters.get('dtypes', {})
1065
1087
  dtypes.update({col: 'json' for col in new_json_cols})
1066
- self.parameters['dtypes'] = dtypes
1067
-
1068
- if not self.temporary:
1069
- edit_success, edit_msg = self.edit(interactive=False, debug=debug)
1070
- if not edit_success:
1071
- warn(f"Unable to update JSON dtypes for {self}:\n{edit_msg}")
1072
-
1073
- return edit_success, edit_msg
1074
-
1075
- return True, "Success"
1088
+ return self.update_parameters({'dtypes': dtypes}, debug=debug)
1076
1089
 
1077
1090
 
1078
1091
  def _persist_new_bytes_columns(self, df, debug: bool = False) -> SuccessTuple:
@@ -1089,16 +1102,7 @@ def _persist_new_bytes_columns(self, df, debug: bool = False) -> SuccessTuple:
1089
1102
  self._attributes_sync_time = None
1090
1103
  dtypes = self.parameters.get('dtypes', {})
1091
1104
  dtypes.update({col: 'bytes' for col in new_bytes_cols})
1092
- self.parameters['dtypes'] = dtypes
1093
-
1094
- if not self.temporary:
1095
- edit_success, edit_msg = self.edit(interactive=False, debug=debug)
1096
- if not edit_success:
1097
- warn(f"Unable to update bytes dtypes for {self}:\n{edit_msg}")
1098
-
1099
- return edit_success, edit_msg
1100
-
1101
- return True, "Success"
1105
+ return self.update_parameters({'dtypes': dtypes}, debug=debug)
1102
1106
 
1103
1107
 
1104
1108
  def _persist_new_geometry_columns(self, df, debug: bool = False) -> SuccessTuple:
@@ -1146,13 +1150,4 @@ def _persist_new_geometry_columns(self, df, debug: bool = False) -> SuccessTuple
1146
1150
  new_cols_types[col] = f"{new_dtype}{modifier}"
1147
1151
 
1148
1152
  dtypes.update(new_cols_types)
1149
- self.parameters['dtypes'] = dtypes
1150
-
1151
- if not self.temporary:
1152
- edit_success, edit_msg = self.edit(interactive=False, debug=debug)
1153
- if not edit_success:
1154
- warn(f"Unable to update bytes dtypes for {self}:\n{edit_msg}")
1155
-
1156
- return edit_success, edit_msg
1157
-
1158
- return True, "Success"
1153
+ return self.update_parameters({'dtypes': dtypes})
@@ -12,7 +12,7 @@ import time
12
12
  import meerschaum as mrsm
13
13
  from meerschaum.utils.typing import SuccessTuple, Any, Optional, Union, Tuple, Dict
14
14
  from meerschaum.utils.warnings import warn, info
15
- from meerschaum.config.static import STATIC_CONFIG
15
+ from meerschaum._internal.static import STATIC_CONFIG
16
16
 
17
17
 
18
18
  def verify(
@@ -22,19 +22,13 @@ from meerschaum.utils.typing import (
22
22
  Union,
23
23
  )
24
24
  from meerschaum.utils.warnings import error, warn
25
- from meerschaum.config import get_config
26
- from meerschaum.config._paths import (
27
- PLUGINS_RESOURCES_PATH,
28
- PLUGINS_ARCHIVES_RESOURCES_PATH,
29
- PLUGINS_TEMP_RESOURCES_PATH,
30
- VIRTENV_RESOURCES_PATH,
31
- PLUGINS_DIR_PATHS,
32
- )
33
25
  _tmpversion = None
34
26
  _ongoing_installations = set()
35
27
 
28
+
36
29
  class Plugin:
37
30
  """Handle packaging of Meerschaum plugins."""
31
+
38
32
  def __init__(
39
33
  self,
40
34
  name: str,
@@ -47,7 +41,8 @@ class Plugin:
47
41
  repo_connector: Optional['mrsm.connectors.api.APIConnector'] = None,
48
42
  repo: Union['mrsm.connectors.api.APIConnector', str, None] = None,
49
43
  ):
50
- from meerschaum.config.static import STATIC_CONFIG
44
+ from meerschaum._internal.static import STATIC_CONFIG
45
+ from meerschaum.config.paths import PLUGINS_ARCHIVES_RESOURCES_PATH, VIRTENV_RESOURCES_PATH
51
46
  sep = STATIC_CONFIG['plugins']['repo_separator']
52
47
  _repo = None
53
48
  if sep in name:
@@ -130,6 +125,8 @@ class Plugin:
130
125
  if self.__dict__.get('_module', None) is not None:
131
126
  return self.module.__file__
132
127
 
128
+ from meerschaum.config.paths import PLUGINS_RESOURCES_PATH
129
+
133
130
  potential_dir = PLUGINS_RESOURCES_PATH / self.name
134
131
  if (
135
132
  potential_dir.exists()
@@ -295,6 +292,7 @@ class Plugin:
295
292
  from meerschaum.utils.packages import attempt_import, determine_version, reload_meerschaum
296
293
  from meerschaum.utils.venv import init_venv
297
294
  from meerschaum.utils.misc import safely_extract_tar
295
+ from meerschaum.config.paths import PLUGINS_TEMP_RESOURCES_PATH, PLUGINS_DIR_PATHS
298
296
  old_cwd = os.getcwd()
299
297
  old_version = ''
300
298
  new_version = ''
@@ -722,7 +720,7 @@ class Plugin:
722
720
  """
723
721
  from meerschaum.utils.warnings import warn
724
722
  from meerschaum.config import get_config
725
- from meerschaum.config.static import STATIC_CONFIG
723
+ from meerschaum._internal.static import STATIC_CONFIG
726
724
  from meerschaum.connectors.parse import is_valid_connector_keys
727
725
  plugins = []
728
726
  _deps = self.get_dependencies(debug=debug)
@@ -953,7 +951,7 @@ class Plugin:
953
951
  """
954
952
  Include the repo keys with the plugin's name.
955
953
  """
956
- from meerschaum.config.static import STATIC_CONFIG
954
+ from meerschaum._internal.static import STATIC_CONFIG
957
955
  sep = STATIC_CONFIG['plugins']['repo_separator']
958
956
  return self.name + sep + str(self.repo_connector)
959
957
 
@@ -6,4 +6,4 @@
6
6
  Import the Plugin class.
7
7
  """
8
8
 
9
- from meerschaum.plugins import Plugin
9
+ from meerschaum.core.Plugin._Plugin import Plugin