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
@@ -0,0 +1,262 @@
1
+ #! /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # vim:fenc=utf-8
4
+
5
+ """
6
+ Patch the runtime configuration from environment variables.
7
+ """
8
+
9
+ import os
10
+ import re
11
+ import json
12
+ import contextlib
13
+ import copy
14
+ import pathlib
15
+
16
+ from meerschaum.utils.typing import List, Union, Dict, Any, Optional
17
+ from meerschaum._internal.static import STATIC_CONFIG
18
+
19
+
20
+ def apply_environment_patches(env: Optional[Dict[str, Any]] = None) -> None:
21
+ """
22
+ Apply patches defined in `MRSM_CONFIG` and `MRSM_PATCH`.
23
+ """
24
+ config_var = STATIC_CONFIG['environment']['config']
25
+ patch_var = STATIC_CONFIG['environment']['patch']
26
+ apply_environment_config(config_var, env=env)
27
+ apply_environment_config(patch_var, env=env)
28
+
29
+
30
+ def apply_environment_config(env_var: str, env: Optional[Dict[str, Any]] = None) -> None:
31
+ """
32
+ Parse a dictionary (simple or JSON) from an environment variable
33
+ and apply it to the current configuration.
34
+ """
35
+ from meerschaum.config import get_config, set_config, _config
36
+ from meerschaum.config._patch import apply_patch_to_config
37
+
38
+ env = env if env is not None else os.environ
39
+
40
+ if env_var not in env:
41
+ return
42
+
43
+ from meerschaum.utils.misc import string_to_dict
44
+ try:
45
+ _patch = string_to_dict(str(os.environ[env_var]).lstrip())
46
+ except Exception:
47
+ _patch = None
48
+
49
+ error_msg = (
50
+ f"Environment variable {env_var} is set but cannot be parsed.\n"
51
+ f"Unset {env_var} or change to JSON or simplified dictionary format "
52
+ "(see --help, under params for formatting)\n"
53
+ f"{env_var} is set to:\n{os.environ[env_var]}\n"
54
+ f"Skipping patching os environment into config..."
55
+ )
56
+
57
+ if not isinstance(_patch, dict):
58
+ print(error_msg)
59
+ return
60
+
61
+ valids = []
62
+
63
+ def load_key(key: str) -> Union[Dict[str, Any], None]:
64
+ try:
65
+ c = get_config(key, warn=False)
66
+ except Exception:
67
+ c = None
68
+ return c
69
+
70
+ ### This was multi-threaded, but I ran into all sorts of locking issues.
71
+ keys = list(_patch.keys())
72
+ for key in keys:
73
+ _ = load_key(key)
74
+
75
+ ### Load and patch config files.
76
+ set_config(
77
+ apply_patch_to_config(
78
+ _config(),
79
+ _patch,
80
+ )
81
+ )
82
+
83
+
84
+ def apply_environment_uris(env: Optional[Dict[str, Any]] = None) -> None:
85
+ """
86
+ Patch temporary connectors defined in environment variables which start with
87
+ `MRSM_SQL_` or `MRSM_API_`.
88
+ """
89
+ for env_var in get_connector_env_vars(env=env):
90
+ apply_connector_uri(env_var, env=env)
91
+
92
+
93
+ def get_connector_env_regex() -> str:
94
+ """
95
+ Return the regex pattern for valid environment variable names for instance connectors.
96
+ """
97
+ return STATIC_CONFIG['environment']['uri_regex']
98
+
99
+
100
+ def get_connector_env_vars(env: Optional[Dict[str, Any]] = None) -> List[str]:
101
+ """
102
+ Get the names of the environment variables which match the Meerschaum connector regex.
103
+
104
+ Examples
105
+ --------
106
+ >>> get_connector_environment_vars()
107
+ ['MRSM_SQL_FOO']
108
+ """
109
+ uri_regex = get_connector_env_regex()
110
+ env_vars = []
111
+
112
+ env = env if env is not None else os.environ
113
+
114
+ for env_var in env:
115
+ matched = re.match(uri_regex, env_var)
116
+ if matched is None:
117
+ continue
118
+ if env_var in STATIC_CONFIG['environment'].values():
119
+ continue
120
+ env_vars.append(env_var)
121
+
122
+ return env_vars
123
+
124
+
125
+ def apply_connector_uri(env_var: str, env: Optional[Dict[str, Any]] = None) -> None:
126
+ """
127
+ Parse and validate a URI obtained from an environment variable.
128
+ """
129
+ from meerschaum.config import get_config, set_config, _config
130
+ from meerschaum.config._patch import apply_patch_to_config
131
+ from meerschaum.config._read_config import search_and_substitute_config
132
+ from meerschaum.utils.warnings import warn
133
+
134
+ env = env if env is not None else os.environ
135
+
136
+ if env_var not in env:
137
+ return
138
+
139
+ uri_regex = get_connector_env_regex()
140
+ matched = re.match(uri_regex, env_var)
141
+ groups = matched.groups()
142
+ typ, label = groups[0].lower(), groups[1].lower()
143
+ if not typ or not label:
144
+ return
145
+
146
+ uri = env[env_var]
147
+
148
+ if uri.lstrip().startswith('{') and uri.rstrip().endswith('}'):
149
+ try:
150
+ conn_attrs = json.loads(uri)
151
+ except Exception:
152
+ warn(f"Unable to parse JSON for environment connector '{typ}:{label}'.")
153
+ conn_attrs = {'uri': uri}
154
+ else:
155
+ conn_attrs = {'uri': uri}
156
+
157
+ set_config(
158
+ apply_patch_to_config(
159
+ {'meerschaum': get_config('meerschaum')},
160
+ {'meerschaum': {'connectors': {typ: {label: conn_attrs}}}},
161
+ )
162
+ )
163
+
164
+
165
+ def get_env_vars(env: Optional[Dict[str, Any]] = None) -> List[str]:
166
+ """
167
+ Return all environment variables which begin with `'MRSM_'`.
168
+ """
169
+ prefix = STATIC_CONFIG['environment']['prefix']
170
+ env = env if env is not None else os.environ
171
+ return sorted([env_var for env_var in env if env_var.startswith(prefix)])
172
+
173
+
174
+ @contextlib.contextmanager
175
+ def replace_env(env: Union[Dict[str, Any], None]):
176
+ """
177
+ Temporarily replace environment variables and current configuration.
178
+
179
+ Parameters
180
+ ----------
181
+ env: Dict[str, Any]
182
+ The new environment dictionary to be patched on `os.environ`.
183
+ """
184
+ if env is None:
185
+ try:
186
+ yield
187
+ finally:
188
+ return
189
+
190
+ from meerschaum.config import _config, set_config
191
+ from meerschaum.config.paths import (
192
+ set_root,
193
+ set_plugins_dir_paths,
194
+ set_venvs_dir_path,
195
+ set_config_dir_path,
196
+ ROOT_DIR_PATH,
197
+ PLUGINS_DIR_PATHS,
198
+ VIRTENV_RESOURCES_PATH,
199
+ CONFIG_DIR_PATH,
200
+ )
201
+
202
+ old_environ = dict(os.environ)
203
+ old_config = copy.deepcopy(_config())
204
+ old_root_dir_path = ROOT_DIR_PATH
205
+ old_plugins_dir_paths = PLUGINS_DIR_PATHS
206
+ old_venvs_dir_path = VIRTENV_RESOURCES_PATH
207
+ old_config_dir_path = CONFIG_DIR_PATH
208
+
209
+ os.environ.update(env)
210
+
211
+ root_dir_env_var = STATIC_CONFIG['environment']['root']
212
+ plugins_dir_env_var = STATIC_CONFIG['environment']['plugins']
213
+ config_dir_env_var = STATIC_CONFIG['environment']['config_dir']
214
+ venvs_dir_env_var = STATIC_CONFIG['environment']['venvs']
215
+
216
+ replaced_root = False
217
+ if root_dir_env_var in env:
218
+ root_dir_path = pathlib.Path(env[root_dir_env_var])
219
+ set_root(root_dir_path)
220
+ replaced_root = True
221
+
222
+ replaced_plugins = False
223
+ if plugins_dir_env_var in env:
224
+ plugins_dir_paths = env[plugins_dir_env_var]
225
+ set_plugins_dir_paths(plugins_dir_paths)
226
+ replaced_plugins = True
227
+
228
+ replaced_venvs = False
229
+ if venvs_dir_env_var in env:
230
+ venv_dir_path = pathlib.Path(env[venvs_dir_env_var])
231
+ set_venvs_dir_path(venv_dir_path)
232
+ replaced_venvs = True
233
+
234
+ replaced_config_dir = False
235
+ if config_dir_env_var in env:
236
+ config_dir_path = pathlib.Path(env[config_dir_env_var])
237
+ set_config_dir_path(config_dir_path)
238
+ replaced_config_dir = True
239
+
240
+ apply_environment_patches(env)
241
+ apply_environment_uris(env)
242
+
243
+ try:
244
+ yield
245
+ finally:
246
+ os.environ.clear()
247
+ os.environ.update(old_environ)
248
+
249
+ if replaced_root:
250
+ set_root(old_root_dir_path)
251
+
252
+ if replaced_plugins:
253
+ set_plugins_dir_paths(old_plugins_dir_paths)
254
+
255
+ if replaced_venvs:
256
+ set_venvs_dir_path(old_venvs_dir_path)
257
+
258
+ if replaced_config_dir:
259
+ set_config_dir_path(old_config_dir_path)
260
+
261
+ _config().clear()
262
+ set_config(old_config)
@@ -56,19 +56,22 @@ env_dict['MEERSCHAUM_API_CONFIG'] = json.dumps(
56
56
  {
57
57
  'meerschaum': 'MRSM{!meerschaum}',
58
58
  'system': 'MRSM{!system}',
59
+ 'api': 'MRSM{!api}',
59
60
  },
60
61
  indent=4,
61
62
  ).replace(
62
63
  '"MRSM{!system}"', 'MRSM{!system}'
63
64
  ).replace(
64
- '"MRSM{!meerschaum}"', 'MRSM{!meerschaum}',
65
+ '"MRSM{!meerschaum}"', 'MRSM{!meerschaum}'
66
+ ).replace(
67
+ '"MRSM{!api}"', 'MRSM{!api}'
65
68
  )
66
69
 
67
70
  volumes = {
68
71
  'api_root': '/meerschaum',
69
- 'meerschaum_db_data': '/var/lib/postgresql/data',
72
+ 'meerschaum_db_data': '/home/postgres/pgdata',
70
73
  'grafana_storage': '/var/lib/grafana',
71
- 'valkey_data': '/bitnami/valkey/data',
74
+ 'valkey_data': '/valkey/data',
72
75
  }
73
76
  networks = {
74
77
  'frontend': None,
@@ -122,7 +125,6 @@ default_docker_compose_config = {
122
125
  'POSTGRES_DB': '<DOLLAR>POSTGRES_DB',
123
126
  'POSTGRES_PASSWORD': '<DOLLAR>POSTGRES_PASSWORD',
124
127
  'ALLOW_IP_RANGE': env_dict['ALLOW_IP_RANGE'],
125
- # 'POSTGRES_INITDB_ARGS': '-c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100'
126
128
  },
127
129
  'command': 'postgres -c max_connections=1000 -c shared_buffers=1024MB -c max_prepared_transactions=100',
128
130
  'healthcheck': {
@@ -184,7 +186,7 @@ default_docker_compose_config = {
184
186
  ],
185
187
  },
186
188
  'valkey': {
187
- 'image': 'bitnami/valkey:latest',
189
+ 'image': 'valkey/valkey:latest',
188
190
  'restart': 'always',
189
191
  'environment': {
190
192
  'VALKEY_PASSWORD': '<DOLLAR>VALKEY_PASSWORD',
@@ -152,8 +152,7 @@ class Connector(metaclass=abc.ABCMeta):
152
152
  ------
153
153
  An error if any of the required attributes are missing.
154
154
  """
155
- from meerschaum.utils.warnings import error, warn
156
- from meerschaum.utils.debug import dprint
155
+ from meerschaum.utils.warnings import error
157
156
  from meerschaum.utils.misc import items_str
158
157
  if required_attributes is None:
159
158
  required_attributes = ['type', 'label']
@@ -14,7 +14,7 @@ For ease of use, you can also import from the root `meerschaum` module:
14
14
  from __future__ import annotations
15
15
 
16
16
  import meerschaum as mrsm
17
- from meerschaum.utils.typing import Any, Union, List, Dict
17
+ from meerschaum.utils.typing import Any, Union, List, Dict, Optional
18
18
  from meerschaum.utils.threading import RLock
19
19
  from meerschaum.utils.warnings import warn
20
20
 
@@ -51,6 +51,7 @@ _locks: Dict[str, RLock] = {
51
51
  'connectors' : RLock(),
52
52
  'types' : RLock(),
53
53
  'custom_types' : RLock(),
54
+ 'plugins_types' : RLock(),
54
55
  '_loaded_plugin_connectors': RLock(),
55
56
  'instance_types' : RLock(),
56
57
  }
@@ -58,6 +59,8 @@ _locks: Dict[str, RLock] = {
58
59
  ### Fill this with objects only when connectors are first referenced.
59
60
  types: Dict[str, Any] = {}
60
61
  custom_types: set = set()
62
+ plugins_types: Dict[str, List[str]] = {}
63
+ _known_custom_types: set = set()
61
64
  _loaded_plugin_connectors: bool = False
62
65
 
63
66
 
@@ -72,7 +75,6 @@ def get_connector(
72
75
  Return existing connector or create new connection and store for reuse.
73
76
 
74
77
  You can create new connectors if enough parameters are provided for the given type and flavor.
75
-
76
78
 
77
79
  Parameters
78
80
  ----------
@@ -297,16 +299,23 @@ def make_connector(cls, _is_executor: bool = False):
297
299
  >>>
298
300
  """
299
301
  import re
302
+ from meerschaum.plugins import _get_parent_plugin
300
303
  suffix_regex = (
301
304
  r'connector$'
302
305
  if not _is_executor
303
306
  else r'executor$'
304
307
  )
308
+ plugin_name = _get_parent_plugin(2)
305
309
  typ = re.sub(suffix_regex, '', cls.__name__.lower())
306
310
  with _locks['types']:
307
311
  types[typ] = cls
308
312
  with _locks['custom_types']:
309
313
  custom_types.add(typ)
314
+ if plugin_name:
315
+ with _locks['plugins_types']:
316
+ if plugin_name not in plugins_types:
317
+ plugins_types[plugin_name] = []
318
+ plugins_types[plugin_name].append(typ)
310
319
  with _locks['connectors']:
311
320
  if typ not in connectors:
312
321
  connectors[typ] = {}
@@ -337,6 +346,30 @@ def load_plugin_connectors():
337
346
  import_plugins(*to_import)
338
347
 
339
348
 
349
+ def unload_plugin_connectors(
350
+ plugin_names: Optional[List[str]] = None,
351
+ debug: bool = False,
352
+ ) -> None:
353
+ """
354
+ Unload custom connectors added by plugins.
355
+ """
356
+ from meerschaum.plugins import get_plugins_names
357
+ global custom_types, _known_custom_types, types, plugins_types, connectors
358
+
359
+ plugin_names = plugin_names or get_plugins_names()
360
+
361
+ for plugin_name in plugin_names:
362
+ plugin_types = plugins_types.get(plugin_name, [])
363
+ for typ in plugin_types:
364
+ _ = types.pop(typ, None)
365
+ _ = connectors.pop(typ, None)
366
+ if typ in instance_types:
367
+ instance_types.remove(typ)
368
+
369
+ custom_types.clear()
370
+ custom_types.update(_known_custom_types)
371
+
372
+
340
373
  def get_connector_plugin(
341
374
  connector: Connector,
342
375
  ) -> Union[str, None, mrsm.Plugin]:
@@ -373,3 +406,5 @@ def _load_builtin_custom_connectors():
373
406
  """
374
407
  import meerschaum.jobs.systemd
375
408
  import meerschaum.connectors.valkey
409
+ _known_custom_types.add('valkey')
410
+ _known_custom_types.add('systemd')
@@ -233,4 +233,4 @@ class APIConnector(InstanceConnector):
233
233
  elif 'api_key' in self.__dict__:
234
234
  return 'api_key'
235
235
 
236
- raise ValueError(f"Could not determine the login scheme for '{self}'.")
236
+ return 'password'
@@ -380,3 +380,14 @@ def get_job_is_blocking_on_stdin(self, name: str, debug: bool = False) -> bool:
380
380
  return False
381
381
 
382
382
  return response.json()
383
+
384
+
385
+ def get_job_prompt_kwargs(self, name: str, debug: bool = False) -> Dict[str, Any]:
386
+ """
387
+ Return the kwargs to the blocking `prompt()`, if available.
388
+ """
389
+ response = self.get(JOBS_ENDPOINT + f'/{name}/prompt_kwargs', debug=debug)
390
+ if not response:
391
+ return {}
392
+
393
+ return response.json()
@@ -112,7 +112,13 @@ def fetch_pipes_keys(
112
112
  tags: Optional[List[str]] = None,
113
113
  params: Optional[Dict[str, Any]] = None,
114
114
  debug: bool = False
115
- ) -> Union[List[Tuple[str, str, Union[str, None]]]]:
115
+ ) -> List[
116
+ Union[
117
+ Tuple[str, str, Union[str, None]],
118
+ Tuple[str, str, Union[str, None], List[str]],
119
+ Tuple[str, str, Union[str, None], Dict[str, Any]]
120
+ ]
121
+ ]:
116
122
  """
117
123
  Fetch registered Pipes' keys from the API.
118
124
 
@@ -16,13 +16,20 @@ def get_plugins_pipe(self) -> 'mrsm.Pipe':
16
16
  """
17
17
  Return the internal pipe for syncing plugins metadata.
18
18
  """
19
+ if '_plugins_pipe' in self.__dict__:
20
+ return self._plugins_pipe
21
+
22
+ cache_connector = self.__dict__.get('_cache_connector', None)
19
23
  users_pipe = self.get_users_pipe()
20
24
  user_id_dtype = users_pipe.dtypes.get('user_id', 'uuid')
21
- return mrsm.Pipe(
25
+
26
+ self._plugins_pipe = mrsm.Pipe(
22
27
  'mrsm', 'plugins',
23
28
  instance=self,
24
29
  target='mrsm_plugins',
25
30
  temporary=True,
31
+ cache=True,
32
+ cache_connector_keys=cache_connector,
26
33
  static=True,
27
34
  null_indices=False,
28
35
  columns={
@@ -36,6 +43,7 @@ def get_plugins_pipe(self) -> 'mrsm.Pipe':
36
43
  'version': 'string',
37
44
  },
38
45
  )
46
+ return self._plugins_pipe
39
47
 
40
48
 
41
49
  def register_plugin(self, plugin: Plugin, debug: bool = False) -> mrsm.SuccessTuple:
@@ -15,23 +15,33 @@ import meerschaum as mrsm
15
15
  from meerschaum.core import Token, User
16
16
  from meerschaum.core.User import hash_password
17
17
  from meerschaum._internal.static import STATIC_CONFIG
18
+ from meerschaum.utils.warnings import dprint
18
19
 
19
20
 
20
21
  def get_tokens_pipe(self) -> mrsm.Pipe:
21
22
  """
22
23
  Return the internal pipe for tokens management.
23
24
  """
25
+ if '_tokens_pipe' in self.__dict__:
26
+ return self._tokens_pipe
27
+
24
28
  users_pipe = self.get_users_pipe()
25
- user_id_dtype = users_pipe.dtypes.get('user_id', 'uuid')
29
+ user_id_dtype = (
30
+ users_pipe._attributes.get('parameters', {}).get('dtypes', {}).get('user_id', 'uuid')
31
+ )
32
+
33
+ cache_connector = self.__dict__.get('_cache_connector', None)
26
34
 
27
- return mrsm.Pipe(
35
+ self._tokens_pipe = mrsm.Pipe(
28
36
  'mrsm', 'tokens',
29
37
  instance=self,
30
38
  target='mrsm_tokens',
31
39
  temporary=True,
40
+ cache=True,
41
+ cache_connector_keys=cache_connector,
32
42
  static=True,
33
43
  autotime=True,
34
- null_indices=True,
44
+ null_indices=False,
35
45
  columns={
36
46
  'datetime': 'creation',
37
47
  'primary': 'id',
@@ -51,6 +61,7 @@ def get_tokens_pipe(self) -> mrsm.Pipe:
51
61
  'secret_hash': 'string',
52
62
  },
53
63
  )
64
+ return self._tokens_pipe
54
65
 
55
66
 
56
67
  def register_token(
@@ -200,10 +211,16 @@ def get_tokens(
200
211
  if ids:
201
212
  params['id'] = ids
202
213
 
214
+ if debug:
215
+ dprint(f"Getting tokens with {user_id=}, {params=}")
216
+
203
217
  tokens_df = tokens_pipe.get_data(params=params, debug=debug)
204
218
  if tokens_df is None:
205
219
  return []
206
220
 
221
+ if debug:
222
+ dprint(f"Retrieved tokens dataframe:\n{tokens_df}")
223
+
207
224
  tokens_docs = tokens_df.to_dict(orient='records')
208
225
  return [
209
226
  Token(
@@ -18,11 +18,17 @@ def get_users_pipe(self) -> 'mrsm.Pipe':
18
18
  """
19
19
  Return the pipe used for users registration.
20
20
  """
21
- return mrsm.Pipe(
21
+ if '_users_pipe' in self.__dict__:
22
+ return self._users_pipe
23
+
24
+ cache_connector = self.__dict__.get('_cache_connector', None)
25
+ self._users_pipe = mrsm.Pipe(
22
26
  'mrsm', 'users',
23
27
  instance=self,
24
28
  target='mrsm_users',
25
29
  temporary=True,
30
+ cache=True,
31
+ cache_connector_keys=cache_connector,
26
32
  static=True,
27
33
  null_indices=False,
28
34
  columns={
@@ -40,6 +46,7 @@ def get_users_pipe(self) -> 'mrsm.Pipe':
40
46
  'unique': 'username',
41
47
  },
42
48
  )
49
+ return self._users_pipe
43
50
 
44
51
 
45
52
  def register_user(
@@ -111,7 +111,7 @@ def parse_repo_keys(keys: Optional[str] = None, **kw):
111
111
  """Parse the Meerschaum repository value into an APIConnector."""
112
112
  from meerschaum.config import get_config
113
113
  if keys is None:
114
- keys = get_config('meerschaum', 'default_repository', patch=True)
114
+ keys = get_config('meerschaum', 'repository', patch=True)
115
115
  keys = str(keys)
116
116
  if ':' not in keys:
117
117
  keys = 'api:' + keys
@@ -78,6 +78,9 @@ def create_engine(
78
78
  _host = self.__dict__.get('host', None)
79
79
  _port = self.__dict__.get('port', None)
80
80
  _database = self.__dict__.get('database', None)
81
+ if _database == '{SQLITE_DB_PATH}':
82
+ from meerschaum.config.paths import SQLITE_DB_PATH
83
+ _database = SQLITE_DB_PATH.as_posix()
81
84
  _options = self.__dict__.get('options', {})
82
85
  if isinstance(_options, str):
83
86
  _options = dict(urllib.parse.parse_qsl(_options))