meerschaum 2.2.3__py3-none-any.whl → 2.2.5__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 (54) hide show
  1. meerschaum/__init__.py +4 -1
  2. meerschaum/_internal/arguments/_parse_arguments.py +23 -14
  3. meerschaum/_internal/arguments/_parser.py +4 -2
  4. meerschaum/_internal/docs/index.py +513 -110
  5. meerschaum/_internal/entry.py +2 -4
  6. meerschaum/_internal/shell/Shell.py +0 -3
  7. meerschaum/actions/__init__.py +5 -1
  8. meerschaum/actions/bootstrap.py +32 -7
  9. meerschaum/actions/delete.py +62 -0
  10. meerschaum/actions/edit.py +98 -15
  11. meerschaum/actions/python.py +45 -14
  12. meerschaum/actions/show.py +39 -4
  13. meerschaum/actions/stack.py +12 -12
  14. meerschaum/actions/uninstall.py +24 -29
  15. meerschaum/api/__init__.py +0 -1
  16. meerschaum/api/_oauth2.py +17 -0
  17. meerschaum/api/dash/__init__.py +0 -1
  18. meerschaum/api/dash/callbacks/custom.py +1 -1
  19. meerschaum/api/dash/plugins.py +5 -6
  20. meerschaum/api/routes/_login.py +23 -7
  21. meerschaum/config/__init__.py +16 -6
  22. meerschaum/config/_edit.py +1 -1
  23. meerschaum/config/_paths.py +3 -0
  24. meerschaum/config/_version.py +1 -1
  25. meerschaum/config/stack/__init__.py +3 -1
  26. meerschaum/connectors/Connector.py +7 -2
  27. meerschaum/connectors/__init__.py +7 -5
  28. meerschaum/core/Pipe/_data.py +23 -15
  29. meerschaum/core/Pipe/_deduplicate.py +1 -1
  30. meerschaum/core/Pipe/_dtypes.py +5 -0
  31. meerschaum/core/Pipe/_fetch.py +26 -20
  32. meerschaum/core/Pipe/_sync.py +96 -61
  33. meerschaum/plugins/__init__.py +1 -1
  34. meerschaum/plugins/bootstrap.py +333 -0
  35. meerschaum/utils/daemon/Daemon.py +14 -3
  36. meerschaum/utils/daemon/FileDescriptorInterceptor.py +21 -14
  37. meerschaum/utils/daemon/RotatingFile.py +21 -18
  38. meerschaum/utils/dataframe.py +12 -4
  39. meerschaum/utils/debug.py +9 -15
  40. meerschaum/utils/formatting/__init__.py +23 -10
  41. meerschaum/utils/misc.py +117 -11
  42. meerschaum/utils/packages/_packages.py +1 -0
  43. meerschaum/utils/prompt.py +64 -21
  44. meerschaum/utils/typing.py +1 -0
  45. meerschaum/utils/warnings.py +9 -1
  46. meerschaum/utils/yaml.py +32 -1
  47. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/METADATA +5 -1
  48. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/RECORD +54 -53
  49. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/WHEEL +1 -1
  50. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/LICENSE +0 -0
  51. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/NOTICE +0 -0
  52. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/entry_points.txt +0 -0
  53. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/top_level.txt +0 -0
  54. {meerschaum-2.2.3.dist-info → meerschaum-2.2.5.dist-info}/zip-safe +0 -0
@@ -47,9 +47,6 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
47
47
  )
48
48
  )
49
49
 
50
- # if args.get('schedule', None):
51
- # from meerschaum.utils.schedule import schedule_function
52
- # return schedule_function(entry_with_args, **args)
53
50
  return entry_with_args(**args)
54
51
 
55
52
 
@@ -122,11 +119,12 @@ def entry_with_args(
122
119
  def _do_action_wrapper(action_function, plugin_name, **kw):
123
120
  from meerschaum.plugins import Plugin
124
121
  from meerschaum.utils.venv import Venv, active_venvs, deactivate_venv
122
+ from meerschaum.utils.misc import filter_keywords
125
123
  plugin = Plugin(plugin_name) if plugin_name else None
126
124
  with Venv(plugin, debug=kw.get('debug', False)):
127
125
  action_name = ' '.join(action_function.__name__.split('_') + kw.get('action', []))
128
126
  try:
129
- result = action_function(**kw)
127
+ result = action_function(**filter_keywords(action_function, **kw))
130
128
  except Exception as e:
131
129
  if kw.get('debug', False):
132
130
  import traceback
@@ -182,7 +182,6 @@ def _check_complete_keys(line: str) -> Optional[List[str]]:
182
182
  is_trigger = True
183
183
  elif line.endswith(' '):
184
184
  ### return empty list so we don't try to parse an incomplete line.
185
- # print('ABORT')
186
185
  return []
187
186
 
188
187
  from meerschaum.utils.misc import get_connector_labels
@@ -196,8 +195,6 @@ def _check_complete_keys(line: str) -> Optional[List[str]]:
196
195
  if line.rstrip(' ').endswith(trigger):
197
196
  return get_connector_labels()
198
197
 
199
- # args = parse_line(line.rstrip(' '))
200
- # search_term = args[var] if var != 'connector_keys' else args[var][0]
201
198
  return get_connector_labels(search_term=last_word.rstrip(' '))
202
199
 
203
200
  return None
@@ -40,7 +40,11 @@ def get_subactions(
40
40
  for name, f in inspect.getmembers(action_module):
41
41
  if not inspect.isfunction(f):
42
42
  continue
43
- if action_function.__name__ + '_' in name and not name.lstrip('_').startswith('complete'):
43
+
44
+ ### Detect subactions which may contain an underscore prefix.
45
+ if (
46
+ name.lstrip('_').startswith(action_function.__name__.lstrip('_') + '_')
47
+ ):
44
48
  _name = name.replace(action_function.__name__, '')
45
49
  _name = _name.lstrip('_')
46
50
  subactions[_name] = f
@@ -25,6 +25,7 @@ def bootstrap(
25
25
  options = {
26
26
  'pipes' : _bootstrap_pipes,
27
27
  'connectors' : _bootstrap_connectors,
28
+ 'plugins' : _bootstrap_plugins,
28
29
  }
29
30
  return choose_subaction(action, options, **kw)
30
31
 
@@ -102,12 +103,14 @@ def _bootstrap_pipes(
102
103
  )
103
104
  try:
104
105
  ck = choose(
105
- f"Where are the data coming from?\n\n" +
106
- f" Please type the keys of a connector from below,\n" +
107
- f" or enter '{new_label}' to register a new connector.\n\n" +
108
- f" {get_config('formatting', 'emoji', 'connector')} Connector:\n",
106
+ (
107
+ "Where are the data coming from?\n\n" +
108
+ f" Please type the keys of a connector or enter '{new_label}'\n" +
109
+ " to register a new connector.\n\n" +
110
+ f" {get_config('formatting', 'emoji', 'connector')} Connector:"
111
+ ),
109
112
  get_connector_labels() + [new_label],
110
- numeric = False
113
+ numeric = False,
111
114
  )
112
115
  except KeyboardInterrupt:
113
116
  return abort_tuple
@@ -257,8 +260,8 @@ def _bootstrap_connectors(
257
260
  _type = choose(
258
261
  (
259
262
  'Please choose a connector type.\n'
260
- + 'For more information on connectors, '
261
- + 'please visit https://meerschaum.io/reference/connectors'
263
+ + ' See https://meerschaum.io/reference/connectors '
264
+ + 'for documentation on connectors.\n'
262
265
  ),
263
266
  sorted(list(connectors)),
264
267
  default = 'sql'
@@ -382,6 +385,28 @@ def _bootstrap_connectors(
382
385
  return True, "Success"
383
386
 
384
387
 
388
+ def _bootstrap_plugins(
389
+ action: Optional[List[str]] = None,
390
+ debug: bool = False,
391
+ **kwargs: Any
392
+ ) -> SuccessTuple:
393
+ """
394
+ Launch an interactive wizard to guide the user to creating a new plugin.
395
+ """
396
+ from meerschaum.utils.prompt import prompt
397
+ from meerschaum.plugins.bootstrap import bootstrap_plugin
398
+
399
+ if not action:
400
+ action = [prompt("Enter the name of your new plugin:")]
401
+
402
+ for plugin_name in action:
403
+ bootstrap_success, bootstrap_msg = bootstrap_plugin(plugin_name)
404
+ if not bootstrap_success:
405
+ return bootstrap_success, bootstrap_msg
406
+
407
+ return True, "Success"
408
+
409
+
385
410
  ### NOTE: This must be the final statement of the module.
386
411
  ### Any subactions added below these lines will not
387
412
  ### be added to the `help` docstring.
@@ -29,6 +29,7 @@ def delete(
29
29
  'users' : _delete_users,
30
30
  'connectors' : _delete_connectors,
31
31
  'jobs' : _delete_jobs,
32
+ 'venvs' : _delete_venvs,
32
33
  }
33
34
  return choose_subaction(action, options, **kw)
34
35
 
@@ -486,6 +487,67 @@ def _delete_jobs(
486
487
  )
487
488
 
488
489
 
490
+ def _delete_venvs(
491
+ action: Optional[List[str]] = None,
492
+ yes: bool = False,
493
+ force: bool = False,
494
+ **kwargs: Any
495
+ ) -> SuccessTuple:
496
+ """
497
+ Remove virtual environments.
498
+ Specify which venvs to remove, or remove everything at once.
499
+ """
500
+ import os
501
+ import shutil
502
+ import pathlib
503
+ from meerschaum.config.paths import VIRTENV_RESOURCES_PATH
504
+ from meerschaum.utils.venv import venv_exists
505
+ from meerschaum.utils.prompt import yes_no
506
+ from meerschaum.utils.misc import print_options
507
+ from meerschaum.utils.warnings import warn
508
+
509
+ venvs_to_skip = ['mrsm']
510
+ venvs = [
511
+ _venv
512
+ for _venv in action or os.listdir(VIRTENV_RESOURCES_PATH)
513
+ if venv_exists(_venv)
514
+ and _venv not in venvs_to_skip
515
+ ]
516
+
517
+ if not venvs:
518
+ msg = "No venvs to delete."
519
+ if action:
520
+ return False, msg
521
+ return True, msg
522
+
523
+ print_options(
524
+ venvs,
525
+ header = 'Venvs to Delete:',
526
+ **kwargs
527
+ )
528
+ confirm_delete = yes_no(
529
+ (
530
+ "Remove the above venv" + ('s' if len(venvs) != 1 else '') + "?\n "
531
+ + "Run `mrsm upgrade packages` and `mrsm install required` to reinstall dependencies.\n"
532
+ ),
533
+ yes = yes,
534
+ default = 'n',
535
+ force = force,
536
+ )
537
+ if not confirm_delete:
538
+ return True, "Nothing was deleted."
539
+
540
+ for venv in venvs:
541
+ venv_path = pathlib.Path(VIRTENV_RESOURCES_PATH / venv)
542
+ try:
543
+ shutil.rmtree(venv_path)
544
+ except Exception as e:
545
+ error_msg = f"Failed to remove '{venv_path}':\n{e}"
546
+ return False, error_msg
547
+
548
+ msg = f"Removed {len(venvs)} venv" + ('s' if len(venvs) != 1 else '') + '.'
549
+ return True, msg
550
+
489
551
 
490
552
  ### NOTE: This must be the final statement of the module.
491
553
  ### Any subactions added below these lines will not
@@ -7,6 +7,7 @@ Functions for editing elements belong here.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
+ import meerschaum as mrsm
10
11
  from meerschaum.utils.typing import List, Any, SuccessTuple, Optional, Dict
11
12
 
12
13
  def edit(
@@ -22,19 +23,22 @@ def edit(
22
23
  'pipes' : _edit_pipes,
23
24
  'definition': _edit_definition,
24
25
  'users' : _edit_users,
26
+ 'plugins' : _edit_plugins,
25
27
  }
26
28
  return choose_subaction(action, options, **kw)
27
29
 
28
30
 
29
31
  def _complete_edit(
30
- action: Optional[List[str]] = None,
31
- **kw: Any
32
- ) -> List[str]:
32
+ action: Optional[List[str]] = None,
33
+ **kw: Any
34
+ ) -> List[str]:
33
35
  """
34
36
  Override the default Meerschaum `complete_` function.
35
37
  """
36
38
  options = {
37
39
  'config': _complete_edit_config,
40
+ 'plugin': _complete_edit_plugins,
41
+ 'plugins': _complete_edit_plugins,
38
42
  }
39
43
 
40
44
  if action is None:
@@ -78,7 +82,7 @@ def _edit_config(action : Optional[List[str]] = None, **kw : Any) -> SuccessTupl
78
82
  action.append('meerschaum')
79
83
  return edit_config(keys=action, **kw)
80
84
 
81
- def _complete_edit_config(action: Optional[List[str]] = None, **kw : Any) -> List[str]:
85
+ def _complete_edit_config(action: Optional[List[str]] = None, **kw: Any) -> List[str]:
82
86
  from meerschaum.config._read_config import get_possible_keys
83
87
  keys = get_possible_keys()
84
88
  if not action:
@@ -172,9 +176,9 @@ def _edit_pipes(
172
176
 
173
177
 
174
178
  def _edit_definition(
175
- action: Optional[List[str]] = None,
176
- **kw
177
- ) -> SuccessTuple:
179
+ action: Optional[List[str]] = None,
180
+ **kw
181
+ ) -> SuccessTuple:
178
182
  """
179
183
  Edit pipes' definitions.
180
184
  Alias for `edit pipes definition`.
@@ -183,13 +187,13 @@ def _edit_definition(
183
187
 
184
188
 
185
189
  def _edit_users(
186
- action: Optional[List[str]] = None,
187
- mrsm_instance: Optional[str] = None,
188
- yes: bool = False,
189
- noask: bool = False,
190
- debug: bool = False,
191
- **kw: Any
192
- ) -> SuccessTuple:
190
+ action: Optional[List[str]] = None,
191
+ mrsm_instance: Optional[str] = None,
192
+ yes: bool = False,
193
+ noask: bool = False,
194
+ debug: bool = False,
195
+ **kw: Any
196
+ ) -> SuccessTuple:
193
197
  """
194
198
  Edit users' registration information.
195
199
  """
@@ -262,7 +266,7 @@ def _edit_users(
262
266
  if not action:
263
267
  return False, "No users to edit."
264
268
 
265
- success = dict()
269
+ success = {}
266
270
  for username in action:
267
271
  try:
268
272
  user = build_user(username)
@@ -289,6 +293,85 @@ def _edit_users(
289
293
  info(msg)
290
294
  return True, msg
291
295
 
296
+
297
+ def _edit_plugins(
298
+ action: Optional[List[str]] = None,
299
+ debug: bool = False,
300
+ **kwargs: Any
301
+ ):
302
+ """
303
+ Edit a plugin's source code.
304
+ """
305
+ import pathlib
306
+ from meerschaum.utils.warnings import warn
307
+ from meerschaum.utils.prompt import prompt, yes_no
308
+ from meerschaum.utils.misc import edit_file
309
+ from meerschaum.utils.packages import reload_meerschaum
310
+ from meerschaum.actions import actions
311
+
312
+ if not action:
313
+ return False, "Specify which plugin to edit."
314
+
315
+ for plugin_name in action:
316
+ plugin = mrsm.Plugin(plugin_name)
317
+
318
+ if not plugin.is_installed():
319
+ warn(f"Plugin '{plugin_name}' is not installed.", stack=False)
320
+
321
+ if not yes_no(
322
+ f"Would you like to create a new plugin '{plugin_name}'?",
323
+ **kwargs
324
+ ):
325
+ return False, f"Plugin '{plugin_name}' does not exist."
326
+
327
+ actions['bootstrap'](
328
+ ['plugins', plugin_name],
329
+ debug = debug,
330
+ **kwargs
331
+ )
332
+ continue
333
+
334
+ plugin_file_path = pathlib.Path(plugin.__file__).resolve()
335
+
336
+ try:
337
+ _ = prompt(f"Press [Enter] to open '{plugin_file_path}':", icon=False)
338
+ except (KeyboardInterrupt, Exception):
339
+ continue
340
+
341
+ edit_file(plugin_file_path)
342
+ reload_meerschaum(debug=debug)
343
+
344
+ return True, "Success"
345
+
346
+
347
+ def _complete_edit_plugins(
348
+ action: Optional[List[str]] = None,
349
+ line: Optional[str] = None,
350
+ **kw: Any
351
+ ) -> List[str]:
352
+ from meerschaum.plugins import get_plugins_names
353
+ plugins_names = get_plugins_names(try_import=False)
354
+ if not action:
355
+ return plugins_names
356
+
357
+ last_word = action[-1]
358
+ if last_word in plugins_names and (line or '')[-1] == ' ':
359
+ return [
360
+ plugin_name
361
+ for plugin_name in plugins_names
362
+ if plugin_name not in action
363
+ ]
364
+
365
+ possibilities = []
366
+ for plugin_name in plugins_names:
367
+ if (
368
+ plugin_name.startswith(last_word)
369
+ and plugin_name not in action
370
+ ):
371
+ possibilities.append(plugin_name)
372
+ return possibilities
373
+
374
+
292
375
  ### NOTE: This must be the final statement of the module.
293
376
  ### Any subactions added below these lines will not
294
377
  ### be added to the `help` docstring.
@@ -10,8 +10,10 @@ from meerschaum.utils.typing import SuccessTuple, Any, List, Optional
10
10
 
11
11
  def python(
12
12
  action: Optional[List[str]] = None,
13
- venv: Optional[str] = 'mrsm',
14
13
  sub_args: Optional[List[str]] = None,
14
+ nopretty: bool = False,
15
+ noask: bool = False,
16
+ venv: Optional[str] = None,
15
17
  debug: bool = False,
16
18
  **kw: Any
17
19
  ) -> SuccessTuple:
@@ -24,8 +26,22 @@ def python(
24
26
 
25
27
  Examples:
26
28
  mrsm python
27
- mrsm python --venv noaa
28
- mrsm python [-i] [-c 'print("hi")']
29
+ mrsm python [-m pip -V]
30
+
31
+ Flags:
32
+ `--nopretty`
33
+ Open a plain Pyhthon REPL rather than ptpython.
34
+
35
+ `--noask`
36
+ Run the supplied Python code and do not open a REPL.
37
+
38
+ `--venv`
39
+ Run the Python interpreter from a virtual environment.
40
+ Will not have Meercshaum imported.
41
+
42
+ `--sub-args` (or flags surrounded by `[]`)
43
+ Rather than run Python code, execute the interpreter with the given sub-flags
44
+ (e.g. `mrsm python [-V]`)
29
45
  """
30
46
  import sys, subprocess, os
31
47
  from meerschaum.utils.debug import dprint
@@ -35,14 +51,16 @@ def python(
35
51
  from meerschaum.config import __version__ as _version
36
52
  from meerschaum.config.paths import VIRTENV_RESOURCES_PATH, PYTHON_RESOURCES_PATH
37
53
  from meerschaum.utils.packages import run_python_package, attempt_import
54
+ from meerschaum.utils.process import run_process
38
55
 
39
56
  if action is None:
40
57
  action = []
41
58
 
42
- if venv == 'None':
43
- venv = None
44
-
45
- joined_actions = ["import meerschaum as mrsm"]
59
+ joined_actions = (
60
+ ["import meerschaum as mrsm"]
61
+ if venv is None and not sub_args
62
+ else []
63
+ )
46
64
  line = ""
47
65
  for i, a in enumerate(action):
48
66
  if a == '':
@@ -73,6 +91,11 @@ def python(
73
91
  '"""); '
74
92
  + 'pts.print_formatted_text(ansi); '
75
93
  )
94
+ if nopretty or venv is not None or sub_args:
95
+ print_command = ""
96
+
97
+ if sub_args:
98
+ nopretty = True
76
99
 
77
100
  command = print_command
78
101
  for a in joined_actions:
@@ -88,19 +111,27 @@ def python(
88
111
  with open(init_script_path, 'w', encoding='utf-8') as f:
89
112
  f.write(command)
90
113
 
91
- env_dict = os.environ.copy()
92
- venv_path = (VIRTENV_RESOURCES_PATH / venv) if venv is not None else None
93
- if venv_path is not None:
94
- env_dict.update({'VIRTUAL_ENV': venv_path.as_posix()})
95
-
96
114
  try:
97
- ptpython = attempt_import('ptpython', venv=venv, allow_outside_venv=False)
115
+ ptpython = attempt_import('ptpython', venv=None)
98
116
  return_code = run_python_package(
99
117
  'ptpython',
100
118
  sub_args or ['--dark-bg', '-i', init_script_path.as_posix()],
119
+ foreground = True,
101
120
  venv = venv,
121
+ ) if not nopretty else run_process(
122
+ (
123
+ [venv_executable(venv)] + (
124
+ sub_args or
125
+ (
126
+ (
127
+ ['-i']
128
+ if not noask
129
+ else []
130
+ ) + [init_script_path.as_posix()]
131
+ )
132
+ )
133
+ ),
102
134
  foreground = True,
103
- env = env_dict,
104
135
  )
105
136
  except KeyboardInterrupt:
106
137
  return_code = 1
@@ -42,6 +42,7 @@ def show(
42
42
  'logs' : _show_logs,
43
43
  'tags' : _show_tags,
44
44
  'schedules' : _show_schedules,
45
+ 'venvs' : _show_venvs,
45
46
  }
46
47
  return choose_subaction(action, show_options, **kw)
47
48
 
@@ -218,15 +219,24 @@ def _show_connectors(
218
219
  from meerschaum.config import get_config
219
220
  from meerschaum.utils.formatting import make_header
220
221
  from meerschaum.utils.formatting import pprint
222
+
223
+ conn_type = action[0].split(':')[0] if action else None
224
+
221
225
  if not nopretty:
222
- print(make_header("\nConfigured connectors:"))
223
- pprint(get_config('meerschaum', 'connectors'), nopretty=nopretty)
224
- if not nopretty:
226
+ print(make_header(
227
+ f"""\nConfigured {"'" + (conn_type + "' ") if conn_type else ''}Connectors:"""
228
+ ))
229
+
230
+ keys = ['meerschaum', 'connectors']
231
+ if conn_type:
232
+ keys.append(conn_type)
233
+ pprint(get_config(*keys), nopretty=nopretty)
234
+ if not nopretty and not conn_type:
225
235
  print(make_header("\nActive connectors:"))
226
236
  pprint(connectors, nopretty=nopretty)
227
237
 
228
238
  from meerschaum.connectors.parse import parse_instance_keys
229
- if action:
239
+ if action and ':' in action[0]:
230
240
  attr, keys = parse_instance_keys(action[0], construct=False, as_tuple=True, debug=debug)
231
241
  if attr:
232
242
  if not nopretty:
@@ -903,6 +913,31 @@ def _show_schedules(
903
913
  return True, "Success"
904
914
 
905
915
 
916
+ def _show_venvs(
917
+ **kwargs: Any
918
+ ):
919
+ """
920
+ Print the available virtual environments in the current MRSM_ROOT_DIR.
921
+ """
922
+ import os
923
+ import pathlib
924
+ from meerschaum.config.paths import VIRTENV_RESOURCES_PATH
925
+ from meerschaum.utils.venv import venv_exists
926
+ from meerschaum.utils.misc import print_options
927
+
928
+ venvs = [
929
+ _venv
930
+ for _venv in os.listdir(VIRTENV_RESOURCES_PATH)
931
+ if venv_exists(_venv)
932
+ ]
933
+ print_options(
934
+ venvs,
935
+ name = 'Venvs:',
936
+ **kwargs
937
+ )
938
+
939
+ return True, "Success"
940
+
906
941
 
907
942
  ### NOTE: This must be the final statement of the module.
908
943
  ### Any subactions added below these lines will not
@@ -7,7 +7,7 @@ Functions for running the Docker Compose stack
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
- from meerschaum.utils.typing import SuccessTuple, Any, List, Optional
10
+ from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Union
11
11
 
12
12
  def stack(
13
13
  action: Optional[List[str]] = None,
@@ -19,7 +19,7 @@ def stack(
19
19
  debug: bool = False,
20
20
  _capture_output: bool = False,
21
21
  **kw: Any
22
- ) -> SuccessTuple:
22
+ ) -> Union[SuccessTuple, 'subprocess.Popen']:
23
23
  """
24
24
  Control the Meerschaum stack with Docker Compose.
25
25
  Usage: `stack {command}`
@@ -147,18 +147,18 @@ def stack(
147
147
  ['docker', 'compose'] if has_builtin_compose
148
148
  else ['docker-compose']
149
149
  ) + cmd_list,
150
- cwd = STACK_COMPOSE_PATH.parent,
151
- stdout = stdout,
152
- stderr = stderr,
153
- env = stack_env_dict,
150
+ cwd=STACK_COMPOSE_PATH.parent,
151
+ stdout=stdout,
152
+ stderr=stderr,
153
+ env=stack_env_dict,
154
154
  ) if (has_builtin_compose or has_binary_compose) else run_python_package(
155
155
  'compose',
156
- args = cmd_list,
157
- cwd = STACK_COMPOSE_PATH.parent,
158
- venv = _compose_venv,
159
- capture_output = _capture_output,
160
- as_proc = True,
161
- env = stack_env_dict,
156
+ args=cmd_list,
157
+ cwd=STACK_COMPOSE_PATH.parent,
158
+ venv=_compose_venv,
159
+ capture_output=_capture_output,
160
+ as_proc=True,
161
+ env=stack_env_dict,
162
162
  )
163
163
  try:
164
164
  rc = proc.wait() if proc is not None else 1
@@ -25,9 +25,9 @@ def uninstall(
25
25
 
26
26
 
27
27
  def _complete_uninstall(
28
- action: Optional[List[str]] = None,
29
- **kw: Any
30
- ) -> List[str]:
28
+ action: Optional[List[str]] = None,
29
+ **kw: Any
30
+ ) -> List[str]:
31
31
  """
32
32
  Override the default Meerschaum `complete_` function.
33
33
  """
@@ -49,15 +49,16 @@ def _complete_uninstall(
49
49
  from meerschaum._internal.shell import default_action_completer
50
50
  return default_action_completer(action=(['uninstall'] + action), **kw)
51
51
 
52
+
52
53
  def _uninstall_plugins(
53
- action: Optional[List[str]] = None,
54
- repository: Optional[str] = None,
55
- yes: bool = False,
56
- force: bool = False,
57
- noask: bool = False,
58
- debug: bool = False,
59
- **kw: Any
60
- ) -> SuccessTuple:
54
+ action: Optional[List[str]] = None,
55
+ repository: Optional[str] = None,
56
+ yes: bool = False,
57
+ force: bool = False,
58
+ noask: bool = False,
59
+ debug: bool = False,
60
+ **kw: Any
61
+ ) -> SuccessTuple:
61
62
  """
62
63
  Remove installed plugins. Does not affect repository registrations.
63
64
  """
@@ -135,26 +136,20 @@ def _uninstall_plugins(
135
136
 
136
137
 
137
138
  def _complete_uninstall_plugins(action: Optional[List[str]] = None, **kw) -> List[str]:
138
- from meerschaum.plugins import get_plugins_names
139
- _plugin_names = get_plugins_names()
140
- if not action:
141
- return _plugin_names
142
- possibilities = []
143
- for name in _plugin_names:
144
- if name.startswith(action[0]) and action[0] != name:
145
- possibilities.append(name)
146
- return possibilities
139
+ from meerschaum.actions.edit import _complete_edit_plugins
140
+ return _complete_edit_plugins(action=action, **kw)
141
+
147
142
 
148
143
  def _uninstall_packages(
149
- action: Optional[List[str]] = None,
150
- sub_args: Optional[List[str]] = None,
151
- venv: Optional[str] = 'mrsm',
152
- yes: bool = False,
153
- force: bool = False,
154
- noask: bool = False,
155
- debug: bool = False,
156
- **kw: Any
157
- ) -> SuccessTuple:
144
+ action: Optional[List[str]] = None,
145
+ sub_args: Optional[List[str]] = None,
146
+ venv: Optional[str] = 'mrsm',
147
+ yes: bool = False,
148
+ force: bool = False,
149
+ noask: bool = False,
150
+ debug: bool = False,
151
+ **kw: Any
152
+ ) -> SuccessTuple:
158
153
  """
159
154
  Uninstall PyPI packages from the Meerschaum virtual environment.
160
155
 
@@ -237,4 +237,3 @@ for module_name, functions_list in _api_plugins.items():
237
237
  + f"when executing function '{function.__name__}' with exception:\n{e}",
238
238
  stack=False,
239
239
  )
240
-