meerschaum 3.0.0rc3__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 (126) 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 +7 -2
  29. meerschaum/api/_oauth2.py +47 -4
  30. meerschaum/api/dash/callbacks/dashboard.py +103 -97
  31. meerschaum/api/dash/callbacks/jobs.py +3 -2
  32. meerschaum/api/dash/callbacks/login.py +10 -1
  33. meerschaum/api/dash/callbacks/pipes.py +136 -57
  34. meerschaum/api/dash/callbacks/register.py +9 -2
  35. meerschaum/api/dash/callbacks/tokens.py +2 -1
  36. meerschaum/api/dash/components.py +6 -7
  37. meerschaum/api/dash/keys.py +17 -1
  38. meerschaum/api/dash/pages/login.py +2 -2
  39. meerschaum/api/dash/pages/pipes.py +14 -4
  40. meerschaum/api/dash/pipes.py +186 -65
  41. meerschaum/api/dash/tokens.py +1 -1
  42. meerschaum/api/dash/webterm.py +14 -6
  43. meerschaum/api/models/_pipes.py +7 -1
  44. meerschaum/api/resources/static/js/terminado.js +3 -0
  45. meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
  46. meerschaum/api/resources/templates/termpage.html +1 -0
  47. meerschaum/api/routes/_jobs.py +23 -11
  48. meerschaum/api/routes/_login.py +73 -5
  49. meerschaum/api/routes/_pipes.py +6 -4
  50. meerschaum/api/routes/_webterm.py +3 -3
  51. meerschaum/config/__init__.py +60 -13
  52. meerschaum/config/_default.py +89 -61
  53. meerschaum/config/_edit.py +10 -8
  54. meerschaum/config/_formatting.py +2 -0
  55. meerschaum/config/_patch.py +4 -2
  56. meerschaum/config/_paths.py +127 -12
  57. meerschaum/config/_read_config.py +20 -10
  58. meerschaum/config/_version.py +1 -1
  59. meerschaum/config/environment.py +262 -0
  60. meerschaum/config/stack/__init__.py +7 -5
  61. meerschaum/connectors/_Connector.py +1 -2
  62. meerschaum/connectors/__init__.py +37 -2
  63. meerschaum/connectors/api/_APIConnector.py +1 -1
  64. meerschaum/connectors/api/_jobs.py +11 -0
  65. meerschaum/connectors/api/_pipes.py +7 -1
  66. meerschaum/connectors/instance/_plugins.py +9 -1
  67. meerschaum/connectors/instance/_tokens.py +20 -3
  68. meerschaum/connectors/instance/_users.py +8 -1
  69. meerschaum/connectors/parse.py +1 -1
  70. meerschaum/connectors/sql/_create_engine.py +3 -0
  71. meerschaum/connectors/sql/_pipes.py +98 -79
  72. meerschaum/connectors/sql/_users.py +8 -1
  73. meerschaum/connectors/sql/tables/__init__.py +20 -3
  74. meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
  75. meerschaum/connectors/valkey/_pipes.py +7 -5
  76. meerschaum/core/Pipe/__init__.py +62 -72
  77. meerschaum/core/Pipe/_attributes.py +66 -90
  78. meerschaum/core/Pipe/_cache.py +555 -0
  79. meerschaum/core/Pipe/_clear.py +0 -11
  80. meerschaum/core/Pipe/_data.py +0 -50
  81. meerschaum/core/Pipe/_deduplicate.py +0 -13
  82. meerschaum/core/Pipe/_delete.py +12 -21
  83. meerschaum/core/Pipe/_drop.py +11 -23
  84. meerschaum/core/Pipe/_dtypes.py +1 -1
  85. meerschaum/core/Pipe/_index.py +8 -14
  86. meerschaum/core/Pipe/_sync.py +12 -18
  87. meerschaum/core/Plugin/_Plugin.py +7 -1
  88. meerschaum/core/Token/_Token.py +1 -1
  89. meerschaum/core/User/_User.py +1 -2
  90. meerschaum/jobs/_Executor.py +88 -4
  91. meerschaum/jobs/_Job.py +135 -35
  92. meerschaum/jobs/systemd.py +7 -2
  93. meerschaum/plugins/__init__.py +277 -81
  94. meerschaum/utils/_get_pipes.py +30 -4
  95. meerschaum/utils/daemon/Daemon.py +195 -41
  96. meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
  97. meerschaum/utils/daemon/RotatingFile.py +63 -36
  98. meerschaum/utils/daemon/StdinFile.py +53 -13
  99. meerschaum/utils/daemon/__init__.py +18 -5
  100. meerschaum/utils/daemon/_names.py +6 -3
  101. meerschaum/utils/debug.py +34 -4
  102. meerschaum/utils/dtypes/__init__.py +5 -1
  103. meerschaum/utils/formatting/__init__.py +4 -1
  104. meerschaum/utils/formatting/_jobs.py +1 -1
  105. meerschaum/utils/formatting/_pipes.py +47 -46
  106. meerschaum/utils/formatting/_pprint.py +1 -0
  107. meerschaum/utils/formatting/_shell.py +16 -6
  108. meerschaum/utils/misc.py +18 -38
  109. meerschaum/utils/packages/__init__.py +15 -13
  110. meerschaum/utils/packages/_packages.py +1 -0
  111. meerschaum/utils/pipes.py +39 -7
  112. meerschaum/utils/process.py +1 -1
  113. meerschaum/utils/prompt.py +171 -144
  114. meerschaum/utils/sql.py +12 -2
  115. meerschaum/utils/threading.py +42 -0
  116. meerschaum/utils/venv/__init__.py +2 -0
  117. meerschaum/utils/warnings.py +19 -13
  118. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/METADATA +3 -1
  119. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/RECORD +125 -119
  120. meerschaum/config/_environment.py +0 -145
  121. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/WHEEL +0 -0
  122. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/entry_points.txt +0 -0
  123. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/LICENSE +0 -0
  124. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/NOTICE +0 -0
  125. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/top_level.txt +0 -0
  126. {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/zip-safe +0 -0
@@ -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))