meerschaum 2.9.4__py3-none-any.whl → 3.0.0__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 (201) 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 +33 -4
  5. meerschaum/_internal/cli/__init__.py +6 -0
  6. meerschaum/_internal/cli/daemons.py +103 -0
  7. meerschaum/_internal/cli/entry.py +220 -0
  8. meerschaum/_internal/cli/workers.py +435 -0
  9. meerschaum/_internal/docs/index.py +48 -2
  10. meerschaum/_internal/entry.py +50 -14
  11. meerschaum/_internal/shell/Shell.py +121 -29
  12. meerschaum/_internal/shell/__init__.py +4 -1
  13. meerschaum/_internal/static.py +359 -0
  14. meerschaum/_internal/term/TermPageHandler.py +1 -2
  15. meerschaum/_internal/term/__init__.py +40 -6
  16. meerschaum/_internal/term/tools.py +33 -8
  17. meerschaum/actions/__init__.py +6 -4
  18. meerschaum/actions/api.py +53 -13
  19. meerschaum/actions/attach.py +1 -0
  20. meerschaum/actions/bootstrap.py +8 -8
  21. meerschaum/actions/delete.py +4 -2
  22. meerschaum/actions/edit.py +171 -25
  23. meerschaum/actions/login.py +8 -8
  24. meerschaum/actions/register.py +143 -6
  25. meerschaum/actions/reload.py +22 -5
  26. meerschaum/actions/restart.py +14 -0
  27. meerschaum/actions/show.py +184 -31
  28. meerschaum/actions/start.py +166 -17
  29. meerschaum/actions/stop.py +38 -2
  30. meerschaum/actions/sync.py +7 -2
  31. meerschaum/actions/tag.py +9 -8
  32. meerschaum/actions/verify.py +5 -8
  33. meerschaum/api/__init__.py +45 -15
  34. meerschaum/api/_events.py +46 -4
  35. meerschaum/api/_oauth2.py +162 -9
  36. meerschaum/api/_tokens.py +102 -0
  37. meerschaum/api/dash/__init__.py +0 -3
  38. meerschaum/api/dash/callbacks/__init__.py +1 -0
  39. meerschaum/api/dash/callbacks/custom.py +4 -3
  40. meerschaum/api/dash/callbacks/dashboard.py +228 -117
  41. meerschaum/api/dash/callbacks/jobs.py +14 -7
  42. meerschaum/api/dash/callbacks/login.py +10 -1
  43. meerschaum/api/dash/callbacks/pipes.py +194 -14
  44. meerschaum/api/dash/callbacks/plugins.py +0 -1
  45. meerschaum/api/dash/callbacks/register.py +10 -3
  46. meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
  47. meerschaum/api/dash/callbacks/tokens.py +389 -0
  48. meerschaum/api/dash/components.py +36 -15
  49. meerschaum/api/dash/jobs.py +1 -1
  50. meerschaum/api/dash/keys.py +35 -93
  51. meerschaum/api/dash/pages/__init__.py +2 -1
  52. meerschaum/api/dash/pages/dashboard.py +1 -20
  53. meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
  54. meerschaum/api/dash/pages/login.py +2 -2
  55. meerschaum/api/dash/pages/pipes.py +16 -5
  56. meerschaum/api/dash/pages/settings/password_reset.py +1 -1
  57. meerschaum/api/dash/pages/tokens.py +53 -0
  58. meerschaum/api/dash/pipes.py +438 -88
  59. meerschaum/api/dash/sessions.py +12 -0
  60. meerschaum/api/dash/tokens.py +603 -0
  61. meerschaum/api/dash/websockets.py +1 -1
  62. meerschaum/api/dash/webterm.py +18 -6
  63. meerschaum/api/models/__init__.py +23 -3
  64. meerschaum/api/models/_actions.py +22 -0
  65. meerschaum/api/models/_pipes.py +91 -7
  66. meerschaum/api/models/_tokens.py +81 -0
  67. meerschaum/api/resources/static/css/dash.css +16 -0
  68. meerschaum/api/resources/static/js/terminado.js +3 -0
  69. meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
  70. meerschaum/api/resources/templates/termpage.html +13 -0
  71. meerschaum/api/routes/__init__.py +1 -0
  72. meerschaum/api/routes/_actions.py +3 -4
  73. meerschaum/api/routes/_connectors.py +3 -7
  74. meerschaum/api/routes/_jobs.py +26 -35
  75. meerschaum/api/routes/_login.py +120 -15
  76. meerschaum/api/routes/_misc.py +5 -10
  77. meerschaum/api/routes/_pipes.py +178 -143
  78. meerschaum/api/routes/_plugins.py +38 -28
  79. meerschaum/api/routes/_tokens.py +236 -0
  80. meerschaum/api/routes/_users.py +47 -35
  81. meerschaum/api/routes/_version.py +3 -3
  82. meerschaum/api/routes/_webterm.py +3 -3
  83. meerschaum/config/__init__.py +100 -30
  84. meerschaum/config/_default.py +132 -64
  85. meerschaum/config/_edit.py +38 -32
  86. meerschaum/config/_formatting.py +2 -0
  87. meerschaum/config/_patch.py +10 -8
  88. meerschaum/config/_paths.py +133 -13
  89. meerschaum/config/_read_config.py +87 -36
  90. meerschaum/config/_sync.py +6 -3
  91. meerschaum/config/_version.py +1 -1
  92. meerschaum/config/environment.py +262 -0
  93. meerschaum/config/stack/__init__.py +37 -15
  94. meerschaum/config/static.py +18 -0
  95. meerschaum/connectors/_Connector.py +11 -6
  96. meerschaum/connectors/__init__.py +41 -22
  97. meerschaum/connectors/api/_APIConnector.py +34 -6
  98. meerschaum/connectors/api/_actions.py +2 -2
  99. meerschaum/connectors/api/_jobs.py +12 -1
  100. meerschaum/connectors/api/_login.py +33 -7
  101. meerschaum/connectors/api/_misc.py +2 -2
  102. meerschaum/connectors/api/_pipes.py +23 -32
  103. meerschaum/connectors/api/_plugins.py +2 -2
  104. meerschaum/connectors/api/_request.py +1 -1
  105. meerschaum/connectors/api/_tokens.py +146 -0
  106. meerschaum/connectors/api/_users.py +70 -58
  107. meerschaum/connectors/instance/_InstanceConnector.py +83 -0
  108. meerschaum/connectors/instance/__init__.py +10 -0
  109. meerschaum/connectors/instance/_pipes.py +442 -0
  110. meerschaum/connectors/instance/_plugins.py +159 -0
  111. meerschaum/connectors/instance/_tokens.py +317 -0
  112. meerschaum/connectors/instance/_users.py +188 -0
  113. meerschaum/connectors/parse.py +5 -2
  114. meerschaum/connectors/sql/_SQLConnector.py +22 -5
  115. meerschaum/connectors/sql/_cli.py +12 -11
  116. meerschaum/connectors/sql/_create_engine.py +12 -168
  117. meerschaum/connectors/sql/_fetch.py +2 -18
  118. meerschaum/connectors/sql/_pipes.py +295 -278
  119. meerschaum/connectors/sql/_plugins.py +29 -0
  120. meerschaum/connectors/sql/_sql.py +47 -22
  121. meerschaum/connectors/sql/_users.py +36 -2
  122. meerschaum/connectors/sql/tables/__init__.py +254 -122
  123. meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
  124. meerschaum/connectors/valkey/_pipes.py +60 -31
  125. meerschaum/connectors/valkey/_plugins.py +2 -26
  126. meerschaum/core/Pipe/__init__.py +115 -85
  127. meerschaum/core/Pipe/_attributes.py +425 -124
  128. meerschaum/core/Pipe/_bootstrap.py +54 -24
  129. meerschaum/core/Pipe/_cache.py +555 -0
  130. meerschaum/core/Pipe/_clear.py +0 -11
  131. meerschaum/core/Pipe/_data.py +96 -68
  132. meerschaum/core/Pipe/_deduplicate.py +0 -13
  133. meerschaum/core/Pipe/_delete.py +12 -21
  134. meerschaum/core/Pipe/_drop.py +11 -23
  135. meerschaum/core/Pipe/_dtypes.py +49 -19
  136. meerschaum/core/Pipe/_edit.py +14 -4
  137. meerschaum/core/Pipe/_fetch.py +1 -1
  138. meerschaum/core/Pipe/_index.py +8 -14
  139. meerschaum/core/Pipe/_show.py +5 -5
  140. meerschaum/core/Pipe/_sync.py +123 -204
  141. meerschaum/core/Pipe/_verify.py +4 -4
  142. meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
  143. meerschaum/core/Plugin/__init__.py +1 -1
  144. meerschaum/core/Token/_Token.py +220 -0
  145. meerschaum/core/Token/__init__.py +12 -0
  146. meerschaum/core/User/_User.py +35 -10
  147. meerschaum/core/User/__init__.py +9 -1
  148. meerschaum/core/__init__.py +1 -0
  149. meerschaum/jobs/_Executor.py +88 -4
  150. meerschaum/jobs/_Job.py +149 -38
  151. meerschaum/jobs/__init__.py +3 -2
  152. meerschaum/jobs/systemd.py +8 -3
  153. meerschaum/models/__init__.py +35 -0
  154. meerschaum/models/pipes.py +247 -0
  155. meerschaum/models/tokens.py +38 -0
  156. meerschaum/models/users.py +26 -0
  157. meerschaum/plugins/__init__.py +301 -88
  158. meerschaum/plugins/bootstrap.py +510 -4
  159. meerschaum/utils/_get_pipes.py +97 -30
  160. meerschaum/utils/daemon/Daemon.py +199 -43
  161. meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
  162. meerschaum/utils/daemon/RotatingFile.py +63 -36
  163. meerschaum/utils/daemon/StdinFile.py +53 -13
  164. meerschaum/utils/daemon/__init__.py +47 -6
  165. meerschaum/utils/daemon/_names.py +6 -3
  166. meerschaum/utils/dataframe.py +480 -82
  167. meerschaum/utils/debug.py +49 -19
  168. meerschaum/utils/dtypes/__init__.py +478 -37
  169. meerschaum/utils/dtypes/sql.py +369 -29
  170. meerschaum/utils/formatting/__init__.py +5 -2
  171. meerschaum/utils/formatting/_jobs.py +1 -1
  172. meerschaum/utils/formatting/_pipes.py +52 -50
  173. meerschaum/utils/formatting/_pprint.py +1 -0
  174. meerschaum/utils/formatting/_shell.py +44 -18
  175. meerschaum/utils/misc.py +268 -186
  176. meerschaum/utils/packages/__init__.py +25 -40
  177. meerschaum/utils/packages/_packages.py +42 -34
  178. meerschaum/utils/pipes.py +213 -0
  179. meerschaum/utils/process.py +2 -2
  180. meerschaum/utils/prompt.py +175 -144
  181. meerschaum/utils/schedule.py +2 -1
  182. meerschaum/utils/sql.py +135 -49
  183. meerschaum/utils/threading.py +42 -0
  184. meerschaum/utils/typing.py +1 -4
  185. meerschaum/utils/venv/_Venv.py +2 -2
  186. meerschaum/utils/venv/__init__.py +7 -7
  187. meerschaum/utils/warnings.py +19 -13
  188. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
  189. meerschaum-3.0.0.dist-info/RECORD +289 -0
  190. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
  191. meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
  192. meerschaum/api/models/_interfaces.py +0 -15
  193. meerschaum/api/models/_locations.py +0 -15
  194. meerschaum/api/models/_metrics.py +0 -15
  195. meerschaum/config/_environment.py +0 -145
  196. meerschaum/config/static/__init__.py +0 -186
  197. meerschaum-2.9.4.dist-info/RECORD +0 -263
  198. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
  199. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
  200. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
  201. {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
@@ -9,14 +9,25 @@ and if interactive, print the welcome message.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
- import os, shutil, sys, pathlib, copy
12
+ import os
13
+ import shutil
14
+ import sys
15
+ import copy
16
+ import contextlib
17
+
13
18
  from meerschaum.utils.typing import Any, Dict, Optional, Union
14
19
  from meerschaum.utils.threading import RLock
15
- from meerschaum.utils.warnings import warn, error
16
20
 
17
21
  from meerschaum.config._version import __version__
18
22
  from meerschaum.config._edit import edit_config, write_config
19
- from meerschaum.config.static import STATIC_CONFIG
23
+ from meerschaum.config._read_config import (
24
+ search_and_substitute_config,
25
+ revert_symlinks_config,
26
+ get_possible_keys,
27
+ get_keyfile_path,
28
+ read_config,
29
+ )
30
+ from meerschaum._internal.static import STATIC_CONFIG
20
31
 
21
32
  from meerschaum.config._paths import (
22
33
  PERMANENT_PATCH_DIR_PATH,
@@ -31,22 +42,40 @@ __all__ = (
31
42
  'write_plugin_config',
32
43
  'get_config',
33
44
  'write_config',
45
+ 'edit_config',
34
46
  'set_config',
47
+ 'replace_config',
48
+ 'search_and_substitute_config',
49
+ 'revert_symlinks_config',
50
+ 'get_possible_keys',
51
+ 'get_keyfile_path',
52
+ 'apply_patch_to_config',
53
+ 'read_config',
35
54
  'paths',
55
+ 'STATIC_CONFIG',
36
56
  )
37
57
  __pdoc__ = {'static': False, 'resources': False, 'stack': False, }
38
58
  _locks = {'config': RLock()}
39
59
 
40
60
  ### apply config preprocessing (e.g. main to meta)
41
61
  config = {}
62
+ _backup_config = None
63
+ _allow_write_missing: bool = True
64
+
65
+
42
66
  def _config(
43
- *keys: str, reload: bool = False, substitute: bool = True,
44
- sync_files: bool = True, write_missing: bool = True,
45
- ) -> Dict[str, Any]:
67
+ *keys: str,
68
+ reload: bool = False,
69
+ substitute: bool = True,
70
+ sync_files: bool = True,
71
+ allow_replaced: bool = True,
72
+ write_missing: bool = True,
73
+ ) -> Dict[str, Any]:
46
74
  """
47
75
  Read and process the configuration file.
48
76
  """
49
- global config
77
+ global config, _backup_config
78
+
50
79
  if config is None or reload:
51
80
  with _locks['config']:
52
81
  config = {}
@@ -56,12 +85,16 @@ def _config(
56
85
  key_config = read_config(
57
86
  keys = [keys[0]],
58
87
  substitute = substitute,
59
- write_missing = write_missing,
88
+ write_missing = write_missing and _allow_write_missing,
60
89
  )
61
90
  if keys[0] in key_config:
62
91
  config[keys[0]] = key_config[keys[0]]
63
- if sync_files:
92
+ if sync_files and _allow_write_missing:
64
93
  _sync_files(keys=[keys[0] if keys else None])
94
+
95
+ if not allow_replaced:
96
+ return _backup_config if _backup_config is not None else config
97
+
65
98
  return config
66
99
 
67
100
 
@@ -137,7 +170,11 @@ def get_config(
137
170
  dprint(f"Indexing keys: {keys}", color=False)
138
171
 
139
172
  if len(keys) == 0:
140
- _rc = _config(substitute=substitute, sync_files=sync_files, write_missing=write_missing)
173
+ _rc = _config(
174
+ substitute=substitute,
175
+ sync_files=sync_files,
176
+ write_missing=(write_missing and _allow_write_missing),
177
+ )
141
178
  if as_tuple:
142
179
  return True, _rc
143
180
  return _rc
@@ -153,18 +190,18 @@ def get_config(
153
190
  ):
154
191
  try:
155
192
  _subbed = search_and_substitute_config({keys[0]: config[keys[0]]})
156
- except Exception as e:
193
+ except Exception:
157
194
  import traceback
158
195
  traceback.print_exc()
196
+ _subbed = {keys[0]: config[keys[0]]}
197
+
159
198
  config[keys[0]] = _subbed[keys[0]]
160
199
  if symlinks_key in _subbed:
161
200
  if symlinks_key not in config:
162
201
  config[symlinks_key] = {}
163
- if keys[0] not in config[symlinks_key]:
164
- config[symlinks_key][keys[0]] = {}
165
- config[symlinks_key][keys[0]] = apply_patch_to_config(
166
- _subbed,
167
- config[symlinks_key][keys[0]]
202
+ config[symlinks_key] = apply_patch_to_config(
203
+ _subbed.get(symlinks_key, {}),
204
+ config.get(symlinks_key, {}),
168
205
  )
169
206
 
170
207
  from meerschaum.config._sync import sync_files as _sync_files
@@ -193,7 +230,7 @@ def get_config(
193
230
  for k in keys:
194
231
  try:
195
232
  c = c[k]
196
- except Exception as e:
233
+ except Exception:
197
234
  invalid_keys = True
198
235
  break
199
236
  if invalid_keys:
@@ -208,7 +245,7 @@ def get_config(
208
245
  for k in keys:
209
246
  try:
210
247
  _c = _c[k]
211
- except Exception as e:
248
+ except Exception:
212
249
  in_default = False
213
250
  if in_default:
214
251
  c = _c
@@ -219,7 +256,7 @@ def get_config(
219
256
  if warn:
220
257
  from meerschaum.utils.warnings import warn as _warn
221
258
  _warn(warning_msg, stacklevel=3, color=False)
222
- except Exception as e:
259
+ except Exception:
223
260
  if warn:
224
261
  print(warning_msg)
225
262
  if as_tuple:
@@ -247,14 +284,15 @@ def get_config(
247
284
 
248
285
 
249
286
  def get_plugin_config(
250
- *keys: str,
251
- warn: bool = False,
252
- **kw: Any
253
- ) -> Optional[Any]:
287
+ *keys: str,
288
+ warn: bool = False,
289
+ **kw: Any
290
+ ) -> Optional[Any]:
254
291
  """
255
292
  This may only be called from within a Meerschaum plugin.
256
293
  See `meerschaum.config.get_config` for arguments.
257
294
  """
295
+ from meerschaum.utils.warnings import error
258
296
  from meerschaum.plugins import _get_parent_plugin
259
297
  parent_plugin_name = _get_parent_plugin(2)
260
298
  if parent_plugin_name is None:
@@ -271,16 +309,17 @@ def get_plugin_config(
271
309
 
272
310
 
273
311
  def write_plugin_config(
274
- config_dict: Dict[str, Any],
275
- **kw : Any
276
- ):
312
+ config_dict: Dict[str, Any],
313
+ **kw: Any
314
+ ):
277
315
  """
278
316
  Write a plugin's configuration dictionary.
279
317
  """
318
+ from meerschaum.utils.warnings import error
280
319
  from meerschaum.plugins import _get_parent_plugin
281
320
  parent_plugin_name = _get_parent_plugin(2)
282
321
  if parent_plugin_name is None:
283
- error(f"You may only call `get_plugin_config()` from within a Meerschaum plugin.")
322
+ error("You may only call `get_plugin_config()` from within a Meerschaum plugin.")
284
323
  plugins_cf = get_config('plugins', warn=False)
285
324
  if plugins_cf is None:
286
325
  plugins_cf = {}
@@ -289,13 +328,44 @@ def write_plugin_config(
289
328
  return write_config(cf, **kw)
290
329
 
291
330
 
331
+ @contextlib.contextmanager
332
+ def replace_config(config_: Union[Dict[str, Any], None]):
333
+ """
334
+ Temporarily override the Meerschaum config dictionary.
335
+
336
+ Parameters
337
+ ----------
338
+ config_: Dict[str, Any]
339
+ The new config dictionary to temporarily replace the canonical `config`.
340
+ """
341
+ if config_ is None:
342
+ try:
343
+ yield
344
+ finally:
345
+ return
346
+
347
+ global _backup_config, _allow_write_missing
348
+
349
+ _backup_config = _config()
350
+ _allow_write_missing = False
351
+ set_config(config_)
352
+
353
+ try:
354
+ yield
355
+ finally:
356
+ set_config(_backup_config)
357
+ _allow_write_missing = True
358
+
292
359
  ### This need to be below get_config to avoid a circular import.
293
360
  from meerschaum.config._read_config import read_config
294
361
 
295
362
  ### If environment variable MRSM_CONFIG or MRSM_PATCH is set, patch config before anything else.
296
- from meerschaum.config._environment import apply_environment_patches, apply_environment_uris
297
- apply_environment_uris()
298
- apply_environment_patches()
363
+ from meerschaum.config.environment import (
364
+ apply_environment_patches as _apply_environment_patches,
365
+ apply_environment_uris as _apply_environment_uris,
366
+ )
367
+ _apply_environment_uris()
368
+ _apply_environment_patches()
299
369
 
300
370
 
301
371
  from meerschaum.config._paths import PATCH_DIR_PATH, PERMANENT_PATCH_DIR_PATH
@@ -6,30 +6,51 @@
6
6
  The default configuration values to write to config.yaml.
7
7
  """
8
8
 
9
- import sys, os, multiprocessing
9
+ import multiprocessing
10
+ from typing import Dict, Any
10
11
 
11
- from meerschaum.connectors import attributes as connector_attributes
12
12
  from meerschaum.config._paths import SQLITE_DB_PATH
13
+ from meerschaum._internal.static import STATIC_CONFIG
13
14
 
15
+ CONNECTOR_ATTRIBUTES: Dict[str, Dict[str, Any]] = {
16
+ 'api': {
17
+ 'required': [
18
+ 'host',
19
+ ],
20
+ 'optional': [
21
+ 'port',
22
+ 'username',
23
+ 'password',
24
+ 'client_id',
25
+ 'client_secret',
26
+ 'api_key',
27
+ ],
28
+ 'default': {
29
+ 'protocol': 'http',
30
+ },
31
+ },
32
+ 'sql': {
33
+ 'flavors': STATIC_CONFIG['sql']['create_engine_flavors'],
34
+ },
35
+ }
14
36
  default_meerschaum_config = {
15
37
  'instance': 'sql:main',
16
38
  'api_instance': 'MRSM{meerschaum:instance}',
17
- 'web_instance': 'MRSM{meerschaum:instance}',
18
- 'default_repository': 'api:mrsm',
39
+ 'repository': 'api:mrsm',
19
40
  'connectors': {
20
41
  'sql': {
21
42
  'default': {},
22
43
  'main': {
23
44
  'username': 'mrsm',
24
45
  'password': 'mrsm',
25
- 'flavor': 'timescaledb',
46
+ 'flavor': 'timescaledb-ha',
26
47
  'host': 'localhost',
27
48
  'database': 'meerschaum',
28
49
  'port': 5432,
29
50
  },
30
51
  'local': {
31
52
  'flavor': 'sqlite',
32
- 'database': str(SQLITE_DB_PATH),
53
+ 'database': "{SQLITE_DB_PATH}",
33
54
  },
34
55
  'memory': {
35
56
  'flavor': 'sqlite',
@@ -37,7 +58,7 @@ default_meerschaum_config = {
37
58
  },
38
59
  },
39
60
  'api': {
40
- 'default': connector_attributes['api']['default'],
61
+ 'default': CONNECTOR_ATTRIBUTES['api']['default'],
41
62
  'main': {
42
63
  'host': 'localhost',
43
64
  'port': 8000,
@@ -73,9 +94,11 @@ default_system_config = {
73
94
  'postgis': True,
74
95
  'citus': True,
75
96
  'timescaledb': True,
97
+ 'timescaledb-ha': True,
76
98
  'mssql': True,
77
99
  },
78
100
  'instance': {
101
+ 'create_metadata_cache_minutes': 14400,
79
102
  'stale_temporary_tables_minutes': 1440,
80
103
  'temporary_target': {
81
104
  'prefix': '_',
@@ -93,59 +116,40 @@ default_system_config = {
93
116
  'connect_args': {},
94
117
  },
95
118
  },
96
-
97
119
  'api': {
98
120
  },
99
121
  },
100
- ### not to be confused with system_config['connectors']['api'], this is the configuration
101
- ### for the API server itself.
102
- 'api': {
103
- 'uvicorn': {
104
- 'app': 'meerschaum.api:app',
105
- 'port': 8000,
106
- 'host': '0.0.0.0',
107
- 'workers': max(int(multiprocessing.cpu_count() / 2), 1),
108
- 'proxy_headers': True,
109
- 'forwarded_allow_ips': '*',
110
- },
111
- 'cache': {
112
- 'connector': 'valkey:main',
113
- 'session_expires_minutes': 43200,
114
- },
115
- 'data': {
116
- 'max_response_row_limit': 100_000,
117
- 'chunks': {
118
- 'ttl_seconds': 1800,
119
- },
120
- },
121
- 'endpoints': {
122
- 'docs_in_production': True,
123
- },
124
- 'permissions': {
125
- 'registration': {
126
- 'users': True,
127
- 'pipes': True,
128
- 'plugins': True,
129
- },
130
- 'actions': {
131
- 'non_admin': True,
132
- },
133
- 'chaining': {
134
- 'insecure_parent_instance': False,
135
- 'child_apis': False,
136
- },
137
- 'instances': {
138
- 'allow_multiple_instances': True,
139
- 'allowed_instance_keys': ['*']
140
- },
141
- },
142
- 'protocol': default_meerschaum_config['connectors']['api']['default']['protocol'],
143
- },
144
- 'webterm': {
145
- 'tmux': {
146
- 'enabled': True,
147
- 'session_suffix': '_mrsm',
148
- },
122
+ 'api': 'MRSM{api}',
123
+ 'webterm': 'MRSM{api:webterm}',
124
+ 'cli': {
125
+ 'max_daemons': (multiprocessing.cpu_count() * 3),
126
+ 'refresh_seconds': 0.1,
127
+ 'allowed_prefixes': ['*'],
128
+ 'disallowed_prefixes': [
129
+ 'edit',
130
+ 'start daemon',
131
+ 'start job',
132
+ 'stop job',
133
+ 'delete job',
134
+ 'stop daemon',
135
+ 'show daemon',
136
+ 'restart daemon',
137
+ 'reload',
138
+ 'start worker',
139
+ 'show log',
140
+ 'python',
141
+ 'login',
142
+ 'executor',
143
+ 'os ',
144
+ 'sh ',
145
+ 'start api',
146
+ 'start webterm',
147
+ 'stack',
148
+ 'instance',
149
+ 'debug',
150
+ 'bootstrap',
151
+ 'daemon',
152
+ ],
149
153
  },
150
154
  'experimental': {
151
155
  'fetch': False,
@@ -156,8 +160,65 @@ default_system_config = {
156
160
  'uv_pip': True,
157
161
  'systemd_healthcheck': False,
158
162
  'valkey_session_cache': True,
163
+ 'cli_daemon': True,
159
164
  },
160
165
  }
166
+
167
+ default_api_config = {
168
+ 'uvicorn': {
169
+ 'app': 'meerschaum.api:app',
170
+ 'port': 8000,
171
+ 'host': '0.0.0.0',
172
+ 'workers': max(int(multiprocessing.cpu_count() / 2), 1),
173
+ 'proxy_headers': True,
174
+ 'forwarded_allow_ips': '*',
175
+ },
176
+ 'cache': {
177
+ 'connector': 'valkey:main',
178
+ 'session_expires_minutes': 43200,
179
+ },
180
+ 'data': {
181
+ 'max_response_row_limit': 100_000,
182
+ 'chunks': {
183
+ 'ttl_seconds': 1800,
184
+ },
185
+ },
186
+ 'endpoints': {
187
+ 'docs_in_production': True,
188
+ },
189
+ 'tokens': {
190
+ 'valid_refresh_minutes': 60,
191
+ 'default_expiration_days': 366,
192
+ },
193
+ 'permissions': {
194
+ 'registration': {
195
+ 'users': True,
196
+ 'pipes': True,
197
+ 'plugins': True,
198
+ },
199
+ 'actions': {
200
+ 'non_admin': True,
201
+ },
202
+ 'chaining': {
203
+ 'insecure_parent_instance': False,
204
+ 'child_apis': False,
205
+ },
206
+ 'instances': {
207
+ 'allow_multiple_instances': True,
208
+ 'allowed_instance_keys': ['*']
209
+ },
210
+ },
211
+ 'protocol': default_meerschaum_config['connectors']['api']['default']['protocol'],
212
+ 'webterm': {
213
+ 'tmux': {
214
+ 'enabled': True,
215
+ 'session_suffix': '_mrsm',
216
+ },
217
+ 'host': '127.0.0.1',
218
+ 'port': 8765,
219
+ },
220
+ }
221
+
161
222
  default_pipes_config = {
162
223
  'parameters': {
163
224
  'columns': {
@@ -172,26 +233,33 @@ default_pipes_config = {
172
233
  },
173
234
  },
174
235
  'attributes': {
175
- 'local_cache_timeout_seconds': 60,
236
+ 'local_cache_timeout_seconds': 600.0,
176
237
  },
177
238
  'sync': {
178
239
  'filter_params_index_limit': 250,
240
+ 'exists_cache_seconds': 60.0,
179
241
  },
180
242
  'verify': {
181
243
  'max_chunks_syncs': 3,
182
244
  },
245
+ 'autotime': {
246
+ 'column_name_if_datetime_missing': 'ts',
247
+ },
248
+ 'dtypes': {
249
+ 'min_ratio_columns_changed_for_full_astype': 0.5,
250
+ 'columns_types_cache_seconds': 60.0,
251
+ },
252
+ 'static': {
253
+ 'static_schema_cache_seconds': 3600.0,
254
+ },
183
255
  }
184
256
  default_plugins_config = {}
185
- default_experimental_config = {
186
- 'venv': True,
187
- }
188
-
189
-
190
257
 
191
258
  ### build default config dictionary
192
259
  default_config = {}
193
260
  default_config['meerschaum'] = default_meerschaum_config
194
261
  default_config['system'] = default_system_config
262
+ default_config['api'] = default_api_config
195
263
  from meerschaum.config._formatting import default_formatting_config
196
264
  default_config['formatting'] = default_formatting_config
197
265
  from meerschaum.config._shell import default_shell_config
@@ -203,7 +271,7 @@ default_config['jobs'] = default_jobs_config
203
271
  ### add configs from other packages
204
272
  try:
205
273
  import meerschaum.config.stack
206
- except ImportError as e:
274
+ except ImportError:
207
275
  pass
208
276
  finally:
209
277
  from meerschaum.config.stack import default_stack_config
@@ -7,8 +7,9 @@ Functions for editing the configuration file
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
+
10
11
  import pathlib
11
- from meerschaum.utils.typing import Optional, Any, SuccessTuple, Mapping, Dict, List, Union
12
+ from meerschaum.utils.typing import Optional, Any, SuccessTuple, Dict, List, Union
12
13
 
13
14
 
14
15
  def edit_config(
@@ -19,20 +20,27 @@ def edit_config(
19
20
  ) -> SuccessTuple:
20
21
  """Edit the configuration files."""
21
22
  from meerschaum.config import get_config, config
22
- from meerschaum.config._read_config import get_keyfile_path, read_config
23
+ from meerschaum.config._read_config import get_keyfile_path, read_config, revert_symlinks_config
23
24
  from meerschaum.config._paths import CONFIG_DIR_PATH
25
+ from meerschaum._internal.static import STATIC_CONFIG
24
26
  from meerschaum.utils.packages import reload_meerschaum
25
27
  from meerschaum.utils.misc import edit_file
26
- from meerschaum.utils.warnings import warn, dprint
28
+ from meerschaum.utils.warnings import warn
27
29
  from meerschaum.utils.prompt import prompt
28
30
 
29
31
  if keys is None:
30
32
  keys = []
31
33
 
34
+ symlinks_key = STATIC_CONFIG['config']['symlinks_key']
32
35
  def _edit_key(key: str):
36
+ new_key_config = None
33
37
  while True:
34
38
  ### If defined in default, create the config file.
35
- key_config = config.pop(key, None)
39
+ symlinks_key_config = config.get(symlinks_key, {}).get(key, {})
40
+ key_config = revert_symlinks_config({
41
+ key: config.pop(key, {}),
42
+ symlinks_key: {key: symlinks_key_config},
43
+ })
36
44
  keyfile_path = get_keyfile_path(key, create_new=True)
37
45
  get_config(key, write_missing=True, warn=False)
38
46
 
@@ -60,7 +68,7 @@ def edit_config(
60
68
  for k in keys:
61
69
  _edit_key(k)
62
70
  except KeyboardInterrupt:
63
- return False, f""
71
+ return False, ""
64
72
 
65
73
  reload_meerschaum(debug=debug)
66
74
  return (True, "Success")
@@ -95,19 +103,23 @@ def write_config(
95
103
  if directory is None:
96
104
  from meerschaum.config._paths import CONFIG_DIR_PATH
97
105
  directory = CONFIG_DIR_PATH
98
- from meerschaum.config.static import STATIC_CONFIG
106
+
107
+ from meerschaum.config import _allow_write_missing
108
+ from meerschaum._internal.static import STATIC_CONFIG
99
109
  from meerschaum.config._default import default_header_comment
100
- from meerschaum.config._patch import apply_patch_to_config
101
- from meerschaum.config._read_config import get_keyfile_path
102
- from meerschaum.utils.debug import dprint
110
+ from meerschaum.config._read_config import get_keyfile_path, revert_symlinks_config
103
111
  from meerschaum.utils.yaml import yaml
104
112
  from meerschaum.utils.misc import filter_keywords
105
- import json, os
113
+ import json
114
+ import os
106
115
  if config_dict is None:
107
116
  from meerschaum.config import _config
108
- cf = _config()
117
+ cf = _config(allow_replaced=False)
109
118
  config_dict = cf
110
119
 
120
+ if not _allow_write_missing:
121
+ return False
122
+
111
123
  default_filetype = STATIC_CONFIG['config']['default_filetype']
112
124
  filetype_dumpers = {
113
125
  'yml' : yaml.dump,
@@ -115,9 +127,7 @@ def write_config(
115
127
  'json' : json.dump,
116
128
  }
117
129
 
118
- symlinks_key = STATIC_CONFIG['config']['symlinks_key']
119
- symlinks = config_dict.pop(symlinks_key) if symlinks_key in config_dict else {}
120
- config_dict = apply_patch_to_config(config_dict, symlinks)
130
+ config_dict = revert_symlinks_config(config_dict)
121
131
 
122
132
  def determine_filetype(k, v):
123
133
  if k == 'meerschaum':
@@ -153,7 +163,7 @@ def write_config(
153
163
  success = True
154
164
  except Exception as e:
155
165
  success = False
156
- print(f"FAILED TO WRITE!")
166
+ print("FAILED TO WRITE!")
157
167
  print(e)
158
168
  print(filter_keywords(
159
169
  filetype_dumpers[filetype],
@@ -165,16 +175,16 @@ def write_config(
165
175
  try:
166
176
  if os.path.exists(filepath):
167
177
  os.remove(filepath)
168
- except Exception as e:
178
+ except Exception:
169
179
  print(f"Failed to write '{k}'")
170
180
  return False
171
181
 
172
182
  return True
173
183
 
174
184
  def general_write_yaml_config(
175
- files: Optional[Dict[pathlib.Path, Dict[str, Any]]] = None,
176
- debug: bool = False
177
- ):
185
+ files: Optional[Dict[pathlib.Path, Dict[str, Any]]] = None,
186
+ debug: bool = False
187
+ ):
178
188
  """
179
189
  Write configuration dictionaries to file paths with optional headers.
180
190
 
@@ -216,18 +226,15 @@ def general_write_yaml_config(
216
226
  return True
217
227
 
218
228
  def general_edit_config(
219
- action: Optional[List[str]] = None,
220
- files: Optional[Dict[str, Union[str, pathlib.Path]]] = None,
221
- default: Optional[str] = None,
222
- debug: bool = False
223
- ):
229
+ action: Optional[List[str]] = None,
230
+ files: Optional[Dict[str, Union[str, pathlib.Path]]] = None,
231
+ default: Optional[str] = None,
232
+ debug: bool = False
233
+ ) -> SuccessTuple:
224
234
  """Prompt the user to edit any config files."""
225
235
  if default is None:
226
236
  raise Exception("Provide a default choice for which file to edit")
227
- import os
228
- from subprocess import call
229
237
  from meerschaum.utils.misc import edit_file
230
- from meerschaum.utils.debug import dprint
231
238
 
232
239
  if files is None:
233
240
  files = {}
@@ -257,11 +264,10 @@ def copy_default_to_config(debug : bool = False):
257
264
  return True
258
265
 
259
266
  def write_default_config(
260
- debug : bool = False,
261
- **kw
262
- ):
267
+ debug: bool = False,
268
+ **kw
269
+ ):
263
270
  """Write the default configuration files."""
264
- import os
265
271
  from meerschaum.config._paths import DEFAULT_CONFIG_DIR_PATH
266
- from meerschaum.config._default import default_config, default_header_comment
272
+ from meerschaum.config._default import default_config
267
273
  return write_config(default_config, directory=DEFAULT_CONFIG_DIR_PATH)