meerschaum 3.0.0rc4__py3-none-any.whl → 3.0.0rc7__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 (117) hide show
  1. meerschaum/_internal/arguments/_parser.py +14 -2
  2. meerschaum/_internal/cli/__init__.py +6 -0
  3. meerschaum/_internal/cli/daemons.py +103 -0
  4. meerschaum/_internal/cli/entry.py +220 -0
  5. meerschaum/_internal/cli/workers.py +434 -0
  6. meerschaum/_internal/docs/index.py +1 -2
  7. meerschaum/_internal/entry.py +44 -8
  8. meerschaum/_internal/shell/Shell.py +113 -19
  9. meerschaum/_internal/shell/__init__.py +4 -1
  10. meerschaum/_internal/static.py +3 -1
  11. meerschaum/_internal/term/TermPageHandler.py +1 -2
  12. meerschaum/_internal/term/__init__.py +40 -6
  13. meerschaum/_internal/term/tools.py +33 -8
  14. meerschaum/actions/__init__.py +6 -4
  15. meerschaum/actions/api.py +39 -11
  16. meerschaum/actions/attach.py +1 -0
  17. meerschaum/actions/delete.py +4 -2
  18. meerschaum/actions/edit.py +27 -8
  19. meerschaum/actions/login.py +8 -8
  20. meerschaum/actions/register.py +13 -7
  21. meerschaum/actions/reload.py +22 -5
  22. meerschaum/actions/restart.py +14 -0
  23. meerschaum/actions/show.py +69 -4
  24. meerschaum/actions/start.py +135 -14
  25. meerschaum/actions/stop.py +36 -3
  26. meerschaum/actions/sync.py +6 -1
  27. meerschaum/api/__init__.py +35 -13
  28. meerschaum/api/_events.py +2 -2
  29. meerschaum/api/_oauth2.py +47 -4
  30. meerschaum/api/dash/callbacks/dashboard.py +29 -0
  31. meerschaum/api/dash/callbacks/jobs.py +3 -2
  32. meerschaum/api/dash/callbacks/login.py +10 -1
  33. meerschaum/api/dash/callbacks/register.py +9 -2
  34. meerschaum/api/dash/pages/login.py +2 -2
  35. meerschaum/api/dash/pipes.py +72 -36
  36. meerschaum/api/dash/webterm.py +14 -6
  37. meerschaum/api/models/_pipes.py +7 -1
  38. meerschaum/api/resources/static/js/terminado.js +3 -0
  39. meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
  40. meerschaum/api/resources/templates/termpage.html +1 -0
  41. meerschaum/api/routes/_jobs.py +23 -11
  42. meerschaum/api/routes/_login.py +73 -5
  43. meerschaum/api/routes/_pipes.py +6 -4
  44. meerschaum/api/routes/_webterm.py +3 -3
  45. meerschaum/config/__init__.py +60 -13
  46. meerschaum/config/_default.py +89 -61
  47. meerschaum/config/_edit.py +10 -8
  48. meerschaum/config/_formatting.py +2 -0
  49. meerschaum/config/_patch.py +4 -2
  50. meerschaum/config/_paths.py +127 -12
  51. meerschaum/config/_read_config.py +20 -10
  52. meerschaum/config/_version.py +1 -1
  53. meerschaum/config/environment.py +262 -0
  54. meerschaum/config/stack/__init__.py +7 -5
  55. meerschaum/connectors/_Connector.py +1 -2
  56. meerschaum/connectors/__init__.py +37 -2
  57. meerschaum/connectors/api/_APIConnector.py +1 -1
  58. meerschaum/connectors/api/_jobs.py +11 -0
  59. meerschaum/connectors/api/_pipes.py +7 -1
  60. meerschaum/connectors/instance/_plugins.py +9 -1
  61. meerschaum/connectors/instance/_tokens.py +20 -3
  62. meerschaum/connectors/instance/_users.py +8 -1
  63. meerschaum/connectors/parse.py +1 -1
  64. meerschaum/connectors/sql/_create_engine.py +3 -0
  65. meerschaum/connectors/sql/_pipes.py +93 -79
  66. meerschaum/connectors/sql/_users.py +8 -1
  67. meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
  68. meerschaum/connectors/valkey/_pipes.py +7 -5
  69. meerschaum/core/Pipe/__init__.py +45 -71
  70. meerschaum/core/Pipe/_attributes.py +66 -90
  71. meerschaum/core/Pipe/_cache.py +555 -0
  72. meerschaum/core/Pipe/_clear.py +0 -11
  73. meerschaum/core/Pipe/_data.py +0 -50
  74. meerschaum/core/Pipe/_deduplicate.py +0 -13
  75. meerschaum/core/Pipe/_delete.py +12 -21
  76. meerschaum/core/Pipe/_drop.py +11 -23
  77. meerschaum/core/Pipe/_dtypes.py +1 -1
  78. meerschaum/core/Pipe/_index.py +8 -14
  79. meerschaum/core/Pipe/_sync.py +12 -18
  80. meerschaum/core/Plugin/_Plugin.py +7 -1
  81. meerschaum/core/Token/_Token.py +1 -1
  82. meerschaum/core/User/_User.py +1 -2
  83. meerschaum/jobs/_Executor.py +88 -4
  84. meerschaum/jobs/_Job.py +135 -35
  85. meerschaum/jobs/systemd.py +7 -2
  86. meerschaum/plugins/__init__.py +277 -81
  87. meerschaum/utils/daemon/Daemon.py +195 -41
  88. meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
  89. meerschaum/utils/daemon/RotatingFile.py +63 -36
  90. meerschaum/utils/daemon/StdinFile.py +53 -13
  91. meerschaum/utils/daemon/__init__.py +18 -5
  92. meerschaum/utils/daemon/_names.py +6 -3
  93. meerschaum/utils/debug.py +34 -4
  94. meerschaum/utils/dtypes/__init__.py +5 -1
  95. meerschaum/utils/formatting/__init__.py +4 -1
  96. meerschaum/utils/formatting/_jobs.py +1 -1
  97. meerschaum/utils/formatting/_pipes.py +47 -46
  98. meerschaum/utils/formatting/_shell.py +16 -6
  99. meerschaum/utils/misc.py +18 -38
  100. meerschaum/utils/packages/__init__.py +15 -13
  101. meerschaum/utils/packages/_packages.py +1 -0
  102. meerschaum/utils/pipes.py +33 -5
  103. meerschaum/utils/process.py +1 -1
  104. meerschaum/utils/prompt.py +171 -144
  105. meerschaum/utils/sql.py +12 -2
  106. meerschaum/utils/threading.py +42 -0
  107. meerschaum/utils/venv/__init__.py +2 -0
  108. meerschaum/utils/warnings.py +19 -13
  109. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/METADATA +3 -1
  110. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/RECORD +116 -110
  111. meerschaum/config/_environment.py +0 -145
  112. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/WHEEL +0 -0
  113. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/entry_points.txt +0 -0
  114. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/LICENSE +0 -0
  115. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/NOTICE +0 -0
  116. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/top_level.txt +0 -0
  117. {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc7.dist-info}/zip-safe +0 -0
@@ -137,7 +137,28 @@ class Pipe:
137
137
  guess_datetime,
138
138
  precision,
139
139
  get_precision,
140
+ )
141
+ from ._cache import (
142
+ _get_cache_connector,
143
+ _cache_value,
144
+ _get_cached_value,
140
145
  _invalidate_cache,
146
+ _get_cache_dir_path,
147
+ _write_cache_key,
148
+ _write_cache_file,
149
+ _write_cache_conn_key,
150
+ _read_cache_key,
151
+ _read_cache_file,
152
+ _read_cache_conn_key,
153
+ _load_cache_keys,
154
+ _load_cache_files,
155
+ _load_cache_conn_keys,
156
+ _get_cache_keys,
157
+ _get_cache_file_keys,
158
+ _get_cache_conn_keys,
159
+ _clear_cache_key,
160
+ _clear_cache_file,
161
+ _clear_cache_conn_key,
141
162
  )
142
163
  from ._show import show
143
164
  from ._edit import edit, edit_definition, update
@@ -176,7 +197,6 @@ class Pipe:
176
197
  target: Optional[str] = None,
177
198
  dtypes: Optional[Dict[str, str]] = None,
178
199
  instance: Optional[Union[str, InstanceConnector]] = None,
179
- temporary: bool = False,
180
200
  upsert: Optional[bool] = None,
181
201
  autoincrement: Optional[bool] = None,
182
202
  autotime: Optional[bool] = None,
@@ -185,14 +205,16 @@ class Pipe:
185
205
  enforce: Optional[bool] = None,
186
206
  null_indices: Optional[bool] = None,
187
207
  mixed_numerics: Optional[bool] = None,
208
+ temporary: bool = False,
209
+ cache: Optional[bool] = None,
210
+ cache_connector_keys: Optional[str] = None,
188
211
  mrsm_instance: Optional[Union[str, InstanceConnector]] = None,
189
- cache: bool = False,
190
- debug: bool = False,
191
212
  connector_keys: Optional[str] = None,
192
213
  metric_key: Optional[str] = None,
193
214
  location_key: Optional[str] = None,
194
215
  instance_keys: Optional[str] = None,
195
216
  indexes: Union[Dict[str, str], List[str], None] = None,
217
+ debug: bool = False,
196
218
  ):
197
219
  """
198
220
  Parameters
@@ -269,9 +291,13 @@ class Pipe:
269
291
  temporary: bool, default False
270
292
  If `True`, prevent instance tables (pipes, users, plugins) from being created.
271
293
 
272
- cache: bool, default False
273
- If `True`, cache fetched data into a local database file.
274
- Defaults to `False`.
294
+ cache: Optional[bool], default None
295
+ If `True`, cache the pipe's metadata to disk (in addition to in-memory caching).
296
+ If `cache` is not explicitly `True`, it is set to `False` if `temporary` is `True`.
297
+ Defaults to `True` (from `None`).
298
+
299
+ cache_connector_keys: Optional[str], default None
300
+ If provided, use the keys to a Valkey connector (e.g. `valkey:main`).
275
301
  """
276
302
  from meerschaum.utils.warnings import error, warn
277
303
  if (not connector and not connector_keys) or (not metric and not metric_key):
@@ -304,8 +330,15 @@ class Pipe:
304
330
  self.metric_key = metric
305
331
  self.location_key = location
306
332
  self.temporary = temporary
333
+ self.cache = cache if cache is not None else (not temporary)
334
+ self.cache_connector_keys = (
335
+ str(cache_connector_keys)
336
+ if cache_connector_keys is not None
337
+ else None
338
+ )
339
+ self.debug = debug
307
340
 
308
- self._attributes = {
341
+ self._attributes: Dict[str, Any] = {
309
342
  'connector_keys': self.connector_keys,
310
343
  'metric_key': self.metric_key,
311
344
  'location_key': self.location_key,
@@ -375,6 +408,7 @@ class Pipe:
375
408
 
376
409
  if isinstance(static, bool):
377
410
  self._attributes['parameters']['static'] = static
411
+ self._static = static
378
412
 
379
413
  if isinstance(enforce, bool):
380
414
  self._attributes['parameters']['enforce'] = enforce
@@ -395,10 +429,12 @@ class Pipe:
395
429
  if not isinstance(_mrsm_instance, str):
396
430
  self._instance_connector = _mrsm_instance
397
431
  self.instance_keys = str(_mrsm_instance)
398
- else: ### NOTE: must be SQL or API Connector for this work
432
+ else:
399
433
  self.instance_keys = _mrsm_instance
400
434
 
401
- self._cache = cache and get_config('system', 'experimental', 'cache')
435
+ if self.instance_keys == 'sql:memory':
436
+ self.cache = False
437
+
402
438
 
403
439
  @property
404
440
  def meta(self):
@@ -456,68 +492,6 @@ class Pipe:
456
492
  return None
457
493
  return self._connector
458
494
 
459
- @property
460
- def cache_connector(self) -> Union['Connector', None]:
461
- """
462
- If the pipe was created with `cache=True`, return the connector to the pipe's
463
- SQLite database for caching.
464
- """
465
- if not self._cache:
466
- return None
467
-
468
- if '_cache_connector' not in self.__dict__:
469
- from meerschaum.connectors import get_connector
470
- from meerschaum.config._paths import DUCKDB_RESOURCES_PATH, SQLITE_RESOURCES_PATH
471
- _resources_path = SQLITE_RESOURCES_PATH
472
- self._cache_connector = get_connector(
473
- 'sql', '_cache_' + str(self),
474
- flavor='sqlite',
475
- database=str(_resources_path / ('_cache_' + str(self) + '.db')),
476
- )
477
-
478
- return self._cache_connector
479
-
480
- @property
481
- def cache_pipe(self) -> Union[mrsm.Pipe, None]:
482
- """
483
- If the pipe was created with `cache=True`, return another `meerschaum.Pipe` used to
484
- manage the local data.
485
- """
486
- if self.cache_connector is None:
487
- return None
488
- if '_cache_pipe' not in self.__dict__:
489
- from meerschaum.config._patch import apply_patch_to_config
490
- from meerschaum.utils.sql import sql_item_name
491
- _parameters = copy.deepcopy(self.parameters)
492
- _fetch_patch = {
493
- 'fetch': ({
494
- 'definition': (
495
- "SELECT * FROM "
496
- + sql_item_name(
497
- str(self.target),
498
- self.instance_connector.flavor,
499
- self.instance_connector.get_pipe_schema(self),
500
- )
501
- ),
502
- }) if self.instance_connector.type == 'sql' else ({
503
- 'connector_keys': self.connector_keys,
504
- 'metric_key': self.metric_key,
505
- 'location_key': self.location_key,
506
- })
507
- }
508
- _parameters = apply_patch_to_config(_parameters, _fetch_patch)
509
- self._cache_pipe = Pipe(
510
- self.instance_keys,
511
- (self.connector_keys + '_' + self.metric_key + '_cache'),
512
- self.location_key,
513
- mrsm_instance=self.cache_connector,
514
- parameters=_parameters,
515
- cache=False,
516
- temporary=True,
517
- )
518
-
519
- return self._cache_pipe
520
-
521
495
  def __str__(self, ansi: bool=False):
522
496
  return pipe_repr(self, ansi=ansi)
523
497
 
@@ -22,30 +22,34 @@ def attributes(self) -> Dict[str, Any]:
22
22
  Return a dictionary of a pipe's keys and parameters.
23
23
  These values are reflected directly from the pipes table of the instance.
24
24
  """
25
- import time
26
25
  from meerschaum.config import get_config
27
26
  from meerschaum.config._patch import apply_patch_to_config
28
27
  from meerschaum.utils.venv import Venv
29
28
  from meerschaum.connectors import get_connector_plugin
29
+ from meerschaum.utils.dtypes import get_current_timestamp
30
30
 
31
31
  timeout_seconds = get_config('pipes', 'attributes', 'local_cache_timeout_seconds')
32
32
 
33
- if '_attributes' not in self.__dict__:
34
- self._attributes = {}
35
-
36
- now = time.perf_counter()
37
- last_refresh = self.__dict__.get('_attributes_sync_time', None)
33
+ now = get_current_timestamp('ms', as_int=True) / 1000
34
+ _attributes_sync_time = self._get_cached_value('_attributes_sync_time', debug=self.debug)
38
35
  timed_out = (
39
- last_refresh is None
36
+ _attributes_sync_time is None
40
37
  or
41
- (timeout_seconds is not None and (now - last_refresh) >= timeout_seconds)
38
+ (timeout_seconds is not None and (now - _attributes_sync_time) >= timeout_seconds)
42
39
  )
43
40
  if not self.temporary and timed_out:
44
- self._attributes_sync_time = now
45
- local_attributes = self.__dict__.get('_attributes', {})
41
+ self._cache_value('_attributes_sync_time', now, memory_only=True, debug=self.debug)
42
+ local_attributes = self._get_cached_value('attributes', debug=self.debug) or {}
46
43
  with Venv(get_connector_plugin(self.instance_connector)):
47
44
  instance_attributes = self.instance_connector.get_pipe_attributes(self)
48
- self._attributes = apply_patch_to_config(instance_attributes, local_attributes)
45
+
46
+ self._cache_value(
47
+ 'attributes',
48
+ apply_patch_to_config(instance_attributes, local_attributes),
49
+ memory_only=True,
50
+ debug=self.debug,
51
+ )
52
+
49
53
  return self._attributes
50
54
 
51
55
 
@@ -78,7 +82,7 @@ def get_parameters(
78
82
  _visited = {self}
79
83
 
80
84
  if refresh:
81
- self._invalidate_cache(hard=True)
85
+ _ = self._invalidate_cache(hard=True)
82
86
 
83
87
  raw_parameters = self.attributes.get('parameters', {})
84
88
  ref_keys = raw_parameters.get('reference')
@@ -131,18 +135,16 @@ def parameters(self) -> Optional[Dict[str, Any]]:
131
135
  """
132
136
  Return the parameters dictionary of the pipe.
133
137
  """
134
- return self.get_parameters()
138
+ return self.get_parameters(debug=self.debug)
135
139
 
136
140
 
137
141
  @parameters.setter
138
- def parameters(self, parameters: Dict[str, Any]) -> None:
142
+ def parameters(self, _parameters: Dict[str, Any]) -> None:
139
143
  """
140
144
  Set the parameters dictionary of the in-memory pipe.
141
145
  Call `meerschaum.Pipe.edit()` to persist changes.
142
146
  """
143
- self._attributes['parameters'] = parameters
144
- if '_parameters' in self.__dict__:
145
- del self.__dict__['_parameters']
147
+ self._attributes['parameters'] = _parameters
146
148
 
147
149
 
148
150
  @property
@@ -175,13 +177,14 @@ def indices(self) -> Union[Dict[str, Union[str, List[str]]], None]:
175
177
  """
176
178
  Return the `indices` dictionary defined in `meerschaum.Pipe.parameters`.
177
179
  """
180
+ _parameters = self.get_parameters(debug=self.debug)
178
181
  indices_key = (
179
182
  'indexes'
180
- if 'indexes' in self.parameters
183
+ if 'indexes' in _parameters
181
184
  else 'indices'
182
185
  )
183
186
 
184
- _indices = self.parameters.get(indices_key, {})
187
+ _indices = _parameters.get(indices_key, {})
185
188
  _columns = self.columns
186
189
  dt_col = _columns.get('datetime', None)
187
190
  if not isinstance(_indices, dict):
@@ -263,7 +266,7 @@ def dtypes(self) -> Dict[str, Any]:
263
266
  """
264
267
  If defined, return the `dtypes` dictionary defined in `meerschaum.Pipe.parameters`.
265
268
  """
266
- return self.get_dtypes(refresh=False)
269
+ return self.get_dtypes(refresh=False, debug=self.debug)
267
270
 
268
271
 
269
272
  @dtypes.setter
@@ -273,8 +276,8 @@ def dtypes(self, _dtypes: Dict[str, Any]) -> None:
273
276
  Call `meerschaum.Pipe.edit()` to persist changes.
274
277
  """
275
278
  self.update_parameters({'dtypes': _dtypes}, persist=False)
276
- _ = self.__dict__.pop('_remote_dtypes', None)
277
- _ = self.__dict__.pop('_remote_dtypes_timestamp', None)
279
+ self._clear_cache_key('_remote_dtypes', debug=self.debug)
280
+ self._clear_cache_key('_remote_dtypes_timestamp', debug=self.debug)
278
281
 
279
282
 
280
283
  def get_dtypes(
@@ -299,10 +302,8 @@ def get_dtypes(
299
302
  -------
300
303
  A dictionary mapping column names to dtypes.
301
304
  """
302
- import time
303
305
  from meerschaum.config._patch import apply_patch_to_config
304
306
  from meerschaum.utils.dtypes import MRSM_ALIAS_DTYPES
305
- from meerschaum._internal.static import STATIC_CONFIG
306
307
  parameters = self.get_parameters(refresh=refresh, debug=debug)
307
308
  configured_dtypes = parameters.get('dtypes', {})
308
309
  if debug:
@@ -361,6 +362,7 @@ def static(self, _static: bool) -> None:
361
362
  Set the `static` parameter for the pipe.
362
363
  """
363
364
  self.update_parameters({'static': _static}, persist=False)
365
+ self._static = _static
364
366
 
365
367
 
366
368
  @property
@@ -400,8 +402,9 @@ def tzinfo(self) -> Union[None, timezone]:
400
402
  """
401
403
  Return `timezone.utc` if the pipe is timezone-aware.
402
404
  """
403
- if '_tzinfo' in self.__dict__:
404
- return self.__dict__['_tzinfo']
405
+ _tzinfo = self._get_cached_value('tzinfo', debug=self.debug)
406
+ if _tzinfo is not None:
407
+ return _tzinfo if _tzinfo != 'None' else None
405
408
 
406
409
  _tzinfo = None
407
410
  dt_col = self.columns.get('datetime', None)
@@ -414,7 +417,7 @@ def tzinfo(self) -> Union[None, timezone]:
414
417
  if dt_typ and 'utc' in dt_typ.lower() or dt_typ == 'datetime':
415
418
  _tzinfo = timezone.utc
416
419
 
417
- self._tzinfo = _tzinfo
420
+ self._cache_value('tzinfo', (_tzinfo if _tzinfo is not None else 'None'), debug=self.debug)
418
421
  return _tzinfo
419
422
 
420
423
 
@@ -541,23 +544,22 @@ def get_columns_types(
541
544
  }
542
545
  >>>
543
546
  """
544
- import time
545
547
  from meerschaum.connectors import get_connector_plugin
546
- from meerschaum._internal.static import STATIC_CONFIG
548
+ from meerschaum.utils.dtypes import get_current_timestamp
547
549
 
548
- now = time.perf_counter()
550
+ now = get_current_timestamp('ms', as_int=True) / 1000
549
551
  cache_seconds = (
550
552
  mrsm.get_config('pipes', 'static', 'static_schema_cache_seconds')
551
553
  if self.static
552
554
  else mrsm.get_config('pipes', 'dtypes', 'columns_types_cache_seconds')
553
555
  )
554
556
  if refresh:
555
- _ = self.__dict__.pop('_columns_types_timestamp', None)
556
- _ = self.__dict__.pop('_columns_types', None)
557
+ self._clear_cache_key('_columns_types_timestamp', debug=debug)
558
+ self._clear_cache_key('_columns_types', debug=debug)
557
559
 
558
- _columns_types = self.__dict__.get('_columns_types', None)
560
+ _columns_types = self._get_cached_value('_columns_types', debug=debug)
559
561
  if _columns_types:
560
- columns_types_timestamp = self.__dict__.get('_columns_types_timestamp', None)
562
+ columns_types_timestamp = self._get_cached_value('_columns_types_timestamp', debug=debug)
561
563
  if columns_types_timestamp is not None:
562
564
  delta = now - columns_types_timestamp
563
565
  if delta < cache_seconds:
@@ -575,8 +577,8 @@ def get_columns_types(
575
577
  else None
576
578
  )
577
579
 
578
- self.__dict__['_columns_types'] = _columns_types
579
- self.__dict__['_columns_types_timestamp'] = now
580
+ self._cache_value('_columns_types', _columns_types, debug=debug)
581
+ self._cache_value('_columns_types_timestamp', now, debug=debug)
580
582
  return _columns_types or {}
581
583
 
582
584
 
@@ -588,22 +590,23 @@ def get_columns_indices(
588
590
  """
589
591
  Return a dictionary mapping columns to index information.
590
592
  """
591
- import time
592
593
  from meerschaum.connectors import get_connector_plugin
593
- from meerschaum._internal.static import STATIC_CONFIG
594
+ from meerschaum.utils.dtypes import get_current_timestamp
594
595
 
595
- now = time.perf_counter()
596
+ now = get_current_timestamp('ms', as_int=True) / 1000
596
597
  cache_seconds = (
597
598
  mrsm.get_config('pipes', 'static', 'static_schema_cache_seconds')
598
599
  if self.static
599
600
  else mrsm.get_config('pipes', 'dtypes', 'columns_types_cache_seconds')
600
601
  )
601
602
  if refresh:
602
- _ = self.__dict__.pop('_columns_indices_timestamp', None)
603
- _ = self.__dict__.pop('_columns_indices', None)
604
- _columns_indices = self.__dict__.get('_columns_indices', None)
603
+ self._clear_cache_key('_columns_indices_timestamp', debug=debug)
604
+ self._clear_cache_key('_columns_indices', debug=debug)
605
+
606
+ _columns_indices = self._get_cached_value('_columns_indices', debug=debug)
607
+
605
608
  if _columns_indices:
606
- columns_indices_timestamp = self.__dict__.get('_columns_indices_timestamp', None)
609
+ columns_indices_timestamp = self._get_cached_value('_columns_indices_timestamp', debug=debug)
607
610
  if columns_indices_timestamp is not None:
608
611
  delta = now - columns_indices_timestamp
609
612
  if delta < cache_seconds:
@@ -621,18 +624,19 @@ def get_columns_indices(
621
624
  else None
622
625
  )
623
626
 
624
- self.__dict__['_columns_indices'] = _columns_indices
625
- self.__dict__['_columns_indices_timestamp'] = now
627
+ self._cache_value('_columns_indices', _columns_indices, debug=debug)
628
+ self._cache_value('_columns_indices_timestamp', now, debug=debug)
626
629
  return {k: v for k, v in _columns_indices.items() if k and v} or {}
627
630
 
628
631
 
629
- def get_id(self, **kw: Any) -> Union[int, None]:
632
+ def get_id(self, **kw: Any) -> Union[int, str, None]:
630
633
  """
631
634
  Fetch a pipe's ID from its instance connector.
632
- If the pipe does not exist, return `None`.
635
+ If the pipe is not registered, return `None`.
633
636
  """
634
637
  if self.temporary:
635
638
  return None
639
+
636
640
  from meerschaum.utils.venv import Venv
637
641
  from meerschaum.connectors import get_connector_plugin
638
642
 
@@ -648,9 +652,12 @@ def id(self) -> Union[int, str, uuid.UUID, None]:
648
652
  """
649
653
  Fetch and cache a pipe's ID.
650
654
  """
651
- if not ('_id' in self.__dict__ and self._id):
652
- self._id = self.get_id()
653
- return self._id
655
+ _id = self._get_cached_value('_id', debug=self.debug)
656
+ if not _id:
657
+ _id = self.get_id(debug=self.debug)
658
+ if _id is not None:
659
+ self._cache_value('_id', _id, debug=self.debug)
660
+ return _id
654
661
 
655
662
 
656
663
  def get_val_column(self, debug: bool = False) -> Union[str, None]:
@@ -914,9 +921,6 @@ def update_parameters(
914
921
  if 'parameters' not in self._attributes:
915
922
  self._attributes['parameters'] = {}
916
923
 
917
- if '_parameters' not in self.__dict__:
918
- self._parameters = {}
919
-
920
924
  self._attributes['parameters'] = apply_patch_to_config(
921
925
  self._attributes['parameters'],
922
926
  parameters_patch,
@@ -943,10 +947,11 @@ def get_precision(self, debug: bool = False) -> Dict[str, Union[str, int]]:
943
947
  )
944
948
  from meerschaum._internal.static import STATIC_CONFIG
945
949
 
946
- if self.__dict__.get('_precision', None):
950
+ _precision = self._get_cached_value('precision', debug=debug)
951
+ if _precision:
947
952
  if debug:
948
- dprint(f"Returning cached precision: {self._precision}")
949
- return self._precision
953
+ dprint(f"Returning cached precision: {_precision}")
954
+ return _precision
950
955
 
951
956
  parameters = self.parameters
952
957
  _precision = parameters.get('precision', {})
@@ -1012,9 +1017,10 @@ def get_precision(self, debug: bool = False) -> Dict[str, Union[str, int]]:
1012
1017
  f"{items_str(list(MRSM_PRECISION_UNITS_SCALARS) + list(MRSM_PRECISION_UNITS_ALIASES))}."
1013
1018
  )
1014
1019
 
1015
- self._precision = {'unit': true_precision_unit}
1020
+ _precision = {'unit': true_precision_unit}
1016
1021
  if precision_interval:
1017
- self._precision['interval'] = precision_interval
1022
+ _precision['interval'] = precision_interval
1023
+ self._cache_value('precision', _precision, debug=debug)
1018
1024
  return self._precision
1019
1025
 
1020
1026
 
@@ -1023,7 +1029,7 @@ def precision(self) -> Dict[str, Union[str, int]]:
1023
1029
  """
1024
1030
  Return the configured or detected precision.
1025
1031
  """
1026
- return self.get_precision()
1032
+ return self.get_precision(debug=self.debug)
1027
1033
 
1028
1034
 
1029
1035
  @precision.setter
@@ -1049,34 +1055,4 @@ def precision(self, _precision: Union[str, Dict[str, Union[str, int]]]) -> None:
1049
1055
  )
1050
1056
 
1051
1057
  self.update_parameters({'precision': true_precision}, persist=False)
1052
- _ = self.__dict__.pop('_precision', None)
1053
-
1054
-
1055
- def _invalidate_cache(
1056
- self,
1057
- hard: bool = False,
1058
- debug: bool = False,
1059
- ) -> None:
1060
- """
1061
- Invalidate temporary metadata cache.
1062
-
1063
- Parameters
1064
- ----------
1065
- hard: bool, default False
1066
- If `True`, clear all temporary cache.
1067
- Otherwise only clear soft cache.
1068
- """
1069
- if debug:
1070
- dprint(f"Invalidating {'some' if not hard else 'all'} cache for {self}.")
1071
-
1072
- self._exists = None
1073
- self._sync_ts = None
1074
-
1075
- if not hard:
1076
- return
1077
-
1078
- _ = self.__dict__.pop('_parameters', None)
1079
- _ = self.__dict__.pop('_precision', None)
1080
- self._columns_types_timestamp = None
1081
- self._columns_types = None
1082
- self._attributes_sync_time = None
1058
+ self._clear_cache_key('precision', debug=self.debug)