meerschaum 2.1.2__py3-none-any.whl → 2.1.3.dev3__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 (35) hide show
  1. meerschaum/__init__.py +10 -4
  2. meerschaum/_internal/docs/index.py +32 -37
  3. meerschaum/_internal/entry.py +3 -0
  4. meerschaum/_internal/shell/Shell.py +106 -78
  5. meerschaum/_internal/shell/ShellCompleter.py +8 -4
  6. meerschaum/actions/__init__.py +2 -1
  7. meerschaum/actions/reload.py +2 -5
  8. meerschaum/actions/show.py +72 -1
  9. meerschaum/actions/sync.py +45 -17
  10. meerschaum/config/_edit.py +10 -34
  11. meerschaum/config/_formatting.py +4 -0
  12. meerschaum/config/_version.py +1 -1
  13. meerschaum/config/static/__init__.py +2 -0
  14. meerschaum/connectors/sql/_pipes.py +26 -20
  15. meerschaum/core/Pipe/_data.py +11 -11
  16. meerschaum/core/Pipe/_fetch.py +4 -4
  17. meerschaum/plugins/_Plugin.py +6 -8
  18. meerschaum/plugins/__init__.py +76 -1
  19. meerschaum/utils/__init__.py +21 -6
  20. meerschaum/utils/daemon/__init__.py +1 -1
  21. meerschaum/utils/formatting/__init__.py +4 -0
  22. meerschaum/utils/formatting/_pipes.py +2 -2
  23. meerschaum/utils/get_pipes.py +1 -1
  24. meerschaum/utils/misc.py +2 -1
  25. meerschaum/utils/packages/__init__.py +46 -7
  26. meerschaum/utils/schedule.py +1 -1
  27. meerschaum/utils/venv/__init__.py +22 -3
  28. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/METADATA +2 -2
  29. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/RECORD +35 -35
  30. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/LICENSE +0 -0
  31. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/NOTICE +0 -0
  32. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/WHEEL +0 -0
  33. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/entry_points.txt +0 -0
  34. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/top_level.txt +0 -0
  35. {meerschaum-2.1.2.dist-info → meerschaum-2.1.3.dev3.dist-info}/zip-safe +0 -0
meerschaum/__init__.py CHANGED
@@ -22,25 +22,31 @@ import atexit
22
22
  from meerschaum.utils.typing import SuccessTuple
23
23
  from meerschaum.core.Pipe import Pipe
24
24
  from meerschaum.plugins import Plugin
25
- from meerschaum.utils import get_pipes
26
25
  from meerschaum.utils.venv import Venv
26
+ from meerschaum.connectors import get_connector
27
+ from meerschaum.utils import get_pipes
27
28
  from meerschaum.utils.formatting import pprint
28
29
  from meerschaum._internal.docs import index as __doc__
29
- from meerschaum.connectors import get_connector
30
30
  from meerschaum.config import __version__, get_config
31
31
  from meerschaum.utils.packages import attempt_import
32
32
  from meerschaum.__main__ import _close_pools
33
33
 
34
34
  atexit.register(_close_pools)
35
35
 
36
- __pdoc__ = {'gui': False, 'api': False, 'core': False,}
36
+ __pdoc__ = {'gui': False, 'api': False, 'core': False, '_internal': False}
37
37
  __all__ = (
38
- "Pipe",
39
38
  "get_pipes",
40
39
  "get_connector",
40
+ "get_config",
41
+ "Pipe",
41
42
  "Plugin",
42
43
  "Venv",
43
44
  "Plugin",
44
45
  "pprint",
45
46
  "attempt_import",
47
+ "actions",
48
+ "config",
49
+ "connectors",
50
+ "plugins",
51
+ "utils",
46
52
  )
@@ -3,7 +3,7 @@
3
3
  # vim:fenc=utf-8
4
4
 
5
5
  """
6
- <img src="https://meerschaum.io/assets/banner_1920x320.png" alt="Meerschaum banner"/>
6
+ <img src="https://meerschaum.io/assets/banner_1920x320.png" alt="Meerschaum banner" style="width: 100%;"/>
7
7
 
8
8
  | PyPI | GitHub | Info | Stats |
9
9
  |---|---|---|---|
@@ -28,17 +28,6 @@ Data engineering often gets in analysts' way, and when work needs to get done, e
28
28
 
29
29
  Rather than copy / pasting your ETL scripts, simply build pipes with Meerschaum! [Meerschaum gives you the tools to design your data streams how you like](https://towardsdatascience.com/easy-time-series-etl-for-data-scientists-with-meerschaum-5aade339b398) ― and don't worry — you can always incorporate Meerschaum into your existing systems!
30
30
 
31
- #### Want to Learn More?
32
-
33
- You can find a wealth of information at [meerschaum.io](https://meerschaum.io)!
34
-
35
- Additionally, below are several articles published about Meerschaum:
36
-
37
- - Interview featured in [*Console 100 - The Open Source Newsletter*](https://console.substack.com/p/console-100)
38
- - [*A Data Scientist's Guide to Fetching COVID-19 Data in 2022*](https://towardsdatascience.com/a-data-scientists-guide-to-fetching-covid-19-data-in-2022-d952b4697) (Towards Data Science)
39
- - [*Time-Series ETL with Meerschaum*](https://towardsdatascience.com/easy-time-series-etl-for-data-scientists-with-meerschaum-5aade339b398) (Towards Data Science)
40
- - [*How I automatically extract my M1 Finance transactions*](https://bmeares.medium.com/how-i-automatically-extract-my-m1-finance-transactions-b43cef857bc7)
41
-
42
31
  ## Features
43
32
 
44
33
  - 📊 **Built for Data Scientists and Analysts**
@@ -58,8 +47,8 @@ Additionally, below are several articles published about Meerschaum:
58
47
  - Manage your database connections with [Meerschaum connectors](https://meerschaum.io/reference/connectors/)
59
48
  - Utility commands with sensible syntax let you control many pipes with grace.
60
49
  - 💼 **Portable from the Start**
61
- - The environment variable `$MRSM_ROOT_DIR` lets you emulate multiple installations and group together your [instances](https://meerschaum.io/reference/connectors/#instances-and-repositories).
62
- - No dependencies required; anything needed will be installed into a virtual environment.
50
+ - The environment variables `$MRSM_ROOT_DIR`, `$MRSM_PLUGINS_DIR`, and `$MRSM_VENVS_DIR` let you emulate multiple installations and group together your [instances](https://meerschaum.io/reference/connectors/#instances-and-repositories).
51
+ - No dependencies required; anything needed will be installed into virtual environments.
63
52
  - [Specify required packages for your plugins](https://meerschaum.io/reference/plugins/writing-plugins/), and users will get those packages in a virtual environment.
64
53
 
65
54
  ## Installation
@@ -81,28 +70,29 @@ Please visit [meerschaum.io](https://meerschaum.io) for setup, usage, and troubl
81
70
  ```python
82
71
  >>> import meerschaum as mrsm
83
72
  >>> pipe = mrsm.Pipe("plugin:noaa", "weather")
84
- >>> df = pipe.get_data(begin='2022-02-02')
85
- >>> df[['timestamp', 'station', 'temperature (wmoUnit:degC)']]
86
- timestamp station temperature (wmoUnit:degC)
87
- 0 2022-03-29 09:54:00 KCEU 8.3
88
- 1 2022-03-29 09:52:00 KATL 10.6
89
- 2 2022-03-29 09:52:00 KCLT 7.2
90
- 3 2022-03-29 08:54:00 KCEU 8.3
91
- 4 2022-03-29 08:52:00 KATL 11.1
92
- ... ... ... ...
93
- 1626 2022-02-02 01:52:00 KATL 10.0
94
- 1627 2022-02-02 01:52:00 KCLT 7.8
95
- 1628 2022-02-02 00:54:00 KCEU 8.3
96
- 1629 2022-02-02 00:52:00 KATL 10.0
97
- 1630 2022-02-02 00:52:00 KCLT 8.3
98
-
99
- [1631 rows x 3 columns]
73
+ >>> cols_to_select = ['timestamp', 'station', 'temperature (degC)']
74
+ >>> df = pipe.get_data(cols_to_select, begin='2023-11-15', end='2023-11-20')
75
+ >>> df
76
+ timestamp station temperature (degC)
77
+ 0 2023-11-15 00:52:00 KATL 16.1
78
+ 1 2023-11-15 00:52:00 KCLT 11.7
79
+ 2 2023-11-15 00:53:00 KGMU 15.0
80
+ 3 2023-11-15 00:54:00 KCEU 13.9
81
+ 4 2023-11-15 01:52:00 KATL 15.6
82
+ .. ... ... ...
83
+ 535 2023-11-19 22:54:00 KCEU 15.6
84
+ 536 2023-11-19 23:52:00 KATL 16.7
85
+ 537 2023-11-19 23:52:00 KCLT 13.9
86
+ 538 2023-11-19 23:53:00 KGMU 15.6
87
+ 539 2023-11-19 23:54:00 KCEU 15.0
88
+
89
+ [540 rows x 3 columns]
100
90
  >>>
101
91
  ```
102
92
 
103
93
  ## Plugins
104
94
 
105
- Here is the [list of community plugins](https://meerschaum.io/reference/plugins/list-of-plugins/) and the [public plugins repository](https://api.mrsm.io/dash/plugins).
95
+ Check out the [Awesome Meerschaum list](https://github.com/bmeares/awesome-meerschaum) for a list of community plugins as well as the [public plugins repository](https://api.mrsm.io/dash/plugins).
106
96
 
107
97
  For details on installing, using, and writing plugins, check out the [plugins documentation](https://meerschaum.io/reference/plugins/types-of-plugins) at [meerschaum.io](https://meerschaum.io).
108
98
 
@@ -123,12 +113,17 @@ def register(pipe, **kw):
123
113
  }
124
114
 
125
115
  def fetch(pipe, **kw):
126
- import datetime, random
127
- return {
128
- 'dt': [datetime.datetime.utcnow()],
129
- 'id': [1],
130
- 'val': [random.randint(0, 100)],
131
- }
116
+ import random
117
+ from datetime import datetime
118
+ docs = [
119
+ {
120
+ 'dt': datetime.now(),
121
+ 'id': i,
122
+ 'val': random.ranint(0, 200),
123
+ }
124
+ for i in range(random.randint(0, 100))
125
+ ]
126
+ return docs
132
127
  ```
133
128
 
134
129
  ## Support Meerschaum's Development
@@ -118,6 +118,7 @@ def entry_with_args(
118
118
  return result
119
119
 
120
120
 
121
+ _shells = []
121
122
  _shell = None
122
123
  def get_shell(
123
124
  sysargs: Optional[List[str]] = None,
@@ -141,4 +142,6 @@ def get_shell(
141
142
  _shell = shell_pkg.Shell(actions, sysargs=sysargs)
142
143
  elif reload:
143
144
  _shell.__init__()
145
+
146
+ _shells.append(_shell)
144
147
  return _shell
@@ -64,6 +64,10 @@ reserved_completers = {
64
64
  'instance', 'repo'
65
65
  }
66
66
 
67
+ ### To handle dynamic reloading, store shell attributes externally.
68
+ ### This is because the shell object address gets lost upon reloads.
69
+ shell_attrs = {}
70
+
67
71
  def _insert_shell_actions(
68
72
  _shell: Optional['Shell'] = None,
69
73
  actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
@@ -229,7 +233,7 @@ class Shell(cmd.Cmd):
229
233
  pass
230
234
 
231
235
  from meerschaum.config._paths import SHELL_HISTORY_PATH
232
- self.session = prompt_toolkit_shortcuts.PromptSession(
236
+ shell_attrs['session'] = prompt_toolkit_shortcuts.PromptSession(
233
237
  history = prompt_toolkit_history.FileHistory(str(SHELL_HISTORY_PATH)),
234
238
  auto_suggest = ValidAutoSuggest(),
235
239
  completer = ShellCompleter(),
@@ -260,15 +264,15 @@ class Shell(cmd.Cmd):
260
264
  pass
261
265
 
262
266
  ### NOTE: custom actions must be added to the self._actions dictionary
263
- self._actions = actions
264
- self._sysargs = sysargs
265
- self._actions['instance'] = self.do_instance
266
- self._actions['repo'] = self.do_repo
267
- self._actions['debug'] = self.do_debug
268
- self._update_bottom_toolbar = True
269
- self._old_bottom_toolbar = ''
270
- self.debug = False
271
- self._reload = True
267
+ shell_attrs['_actions'] = actions
268
+ shell_attrs['_sysargs'] = sysargs
269
+ shell_attrs['_actions']['instance'] = self.do_instance
270
+ shell_attrs['_actions']['repo'] = self.do_repo
271
+ shell_attrs['_actions']['debug'] = self.do_debug
272
+ shell_attrs['_update_bottom_toolbar'] = True
273
+ shell_attrs['_old_bottom_toolbar'] = ''
274
+ shell_attrs['debug'] = False
275
+ shell_attrs['_reload'] = True
272
276
  self.load_config()
273
277
  self.hidden_commands = []
274
278
  ### update hidden commands list (cmd2 only)
@@ -286,7 +290,7 @@ class Shell(cmd.Cmd):
286
290
  from meerschaum.utils.misc import remove_ansi
287
291
  from meerschaum.utils.formatting import CHARSET, ANSI, UNICODE, colored
288
292
 
289
- if self.__dict__.get('intro', None) != '':
293
+ if shell_attrs.get('intro', None) != '':
290
294
  self.intro = get_config('shell', CHARSET, 'intro', patch=patch)
291
295
  self.intro += '\n' + ''.join(
292
296
  [' '
@@ -297,25 +301,30 @@ class Shell(cmd.Cmd):
297
301
  ) + 'v' + version
298
302
  else:
299
303
  self.intro = ""
300
- self._prompt = get_config('shell', CHARSET, 'prompt', patch=patch)
301
- self.prompt = self._prompt
302
- self.ruler = get_config('shell', CHARSET, 'ruler', patch=patch)
303
- self.close_message = get_config('shell', CHARSET, 'close_message', patch=patch)
304
- self.doc_header = get_config('shell', CHARSET, 'doc_header', patch=patch)
305
- self.undoc_header = get_config('shell', CHARSET, 'undoc_header', patch=patch)
304
+ shell_attrs['intro'] = self.intro
305
+ shell_attrs['_prompt'] = get_config('shell', CHARSET, 'prompt', patch=patch)
306
+ self.prompt = shell_attrs['_prompt']
307
+ shell_attrs['ruler'] = get_config('shell', CHARSET, 'ruler', patch=patch)
308
+ self.ruler = shell_attrs['ruler']
309
+ shell_attrs['close_message'] = get_config('shell', CHARSET, 'close_message', patch=patch)
310
+ self.close_message = shell_attrs['close_message']
311
+ shell_attrs['doc_header'] = get_config('shell', CHARSET, 'doc_header', patch=patch)
312
+ self.doc_header = shell_attrs['doc_header']
313
+ shell_attrs['undoc_header'] = get_config('shell', CHARSET, 'undoc_header', patch=patch)
314
+ self.undoc_header = shell_attrs['undoc_header']
306
315
 
307
316
  if instance is None and self.__dict__.get('instance_keys', None) is None:
308
317
  ### create default instance and repository connectors
309
- self.instance_keys = remove_ansi(get_config('meerschaum', 'instance', patch=patch))
310
- ### self.instance is a stylized version of self.instance_keys
311
- self.instance = str(self.instance_keys)
318
+ shell_attrs['instance_keys'] = remove_ansi(get_config('meerschaum', 'instance', patch=patch))
319
+ ### instance is a stylized version of instance_keys
320
+ shell_attrs['instance'] = str(shell_attrs['instance_keys'])
312
321
  else:
313
- self.instance = instance
314
- self.instance_keys = remove_ansi(str(instance))
315
- if self.__dict__.get('repo_keys', None) is None:
316
- self.repo_keys = get_config('meerschaum', 'default_repository', patch=patch)
322
+ shell_attrs['instance'] = instance
323
+ shell_attrs['instance_keys'] = remove_ansi(str(instance))
324
+ if shell_attrs.get('repo_keys', None) is None:
325
+ shell_attrs['repo_keys'] = get_config('meerschaum', 'default_repository', patch=patch)
317
326
  ### this will be updated later in update_prompt ONLY IF {username} is in the prompt
318
- self.username = ''
327
+ shell_attrs['username'] = ''
319
328
 
320
329
  if ANSI:
321
330
  def apply_colors(attr, key):
@@ -325,48 +334,54 @@ class Shell(cmd.Cmd):
325
334
  )
326
335
 
327
336
  for attr_key in get_config('shell', 'ansi'):
328
- if attr_key not in self.__dict__:
337
+ if attr_key not in shell_attrs:
329
338
  continue
330
- self.__dict__[attr_key] = apply_colors(self.__dict__[attr_key], attr_key)
339
+ shell_attrs[attr_key] = apply_colors(shell_attrs[attr_key], attr_key)
340
+ self.__dict__[attr_key] = shell_attrs[attr_key]
331
341
 
332
342
  ### refresh actions
333
343
  _insert_shell_actions(_shell=self, keep_self=True)
334
344
 
335
345
  ### replace {instance} in prompt with stylized instance string
336
346
  self.update_prompt()
337
- self._dict_backup = {k:v for k, v in self.__dict__.copy().items() if k != '_dict_backup'}
338
347
 
339
348
  def insert_actions(self):
340
349
  from meerschaum.actions import actions
341
350
 
342
351
  def update_prompt(self, instance: Optional[str] = None, username: Optional[str] = None):
343
352
  from meerschaum.utils.formatting import ANSI, colored
344
- cmd.__builtins__['input'] = input_with_sigint(_old_input, self.session, shell=self)
345
- prompt = self._prompt
353
+ from meerschaum._internal.entry import _shell, get_shell
354
+
355
+ cmd.__builtins__['input'] = input_with_sigint(
356
+ _old_input,
357
+ shell_attrs['session'],
358
+ shell = self,
359
+ )
360
+ prompt = shell_attrs['_prompt']
346
361
  mask = prompt
347
- self._update_bottom_toolbar = True
362
+ shell_attrs['_update_bottom_toolbar'] = True
348
363
 
349
- if '{instance}' in self._prompt:
364
+ if '{instance}' in shell_attrs['_prompt']:
350
365
  if instance is None:
351
- instance = self.instance_keys
352
- self.instance = instance
366
+ instance = shell_attrs['instance_keys']
367
+ shell_attrs['instance'] = instance
353
368
  if ANSI:
354
- self.instance = colored(
355
- self.instance, **get_config(
369
+ shell_attrs['instance'] = colored(
370
+ shell_attrs['instance'], **get_config(
356
371
  'shell', 'ansi', 'instance', 'rich'
357
372
  )
358
373
  )
359
- prompt = prompt.replace('{instance}', self.instance)
374
+ prompt = prompt.replace('{instance}', shell_attrs['instance'])
360
375
  mask = mask.replace('{instance}', ''.join(['\0' for c in '{instance}']))
361
376
 
362
- if '{username}' in self._prompt:
377
+ if '{username}' in shell_attrs['_prompt']:
363
378
  if username is None:
364
379
  from meerschaum.utils.misc import remove_ansi
365
380
  from meerschaum.connectors.parse import parse_instance_keys
366
381
  from meerschaum.connectors.sql import SQLConnector
367
382
  try:
368
383
  conn_attrs = parse_instance_keys(
369
- remove_ansi(self.instance_keys), construct=False
384
+ remove_ansi(shell_attrs['instance_keys']), construct=False
370
385
  )
371
386
  if 'username' not in conn_attrs:
372
387
  if 'uri' in conn_attrs:
@@ -379,14 +394,14 @@ class Shell(cmd.Cmd):
379
394
  username = str(e)
380
395
  if username is None:
381
396
  username = '(no username)'
382
- self.username = (
397
+ shell_attrs['username'] = (
383
398
  username if not ANSI else
384
399
  colored(username, **get_config('shell', 'ansi', 'username', 'rich'))
385
400
  )
386
- prompt = prompt.replace('{username}', self.username)
401
+ prompt = prompt.replace('{username}', shell_attrs['username'])
387
402
  mask = mask.replace('{username}', ''.join(['\0' for c in '{username}']))
388
403
 
389
- remainder_prompt = list(self._prompt)
404
+ remainder_prompt = list(shell_attrs['_prompt'])
390
405
  for i, c in enumerate(mask):
391
406
  if c != '\0':
392
407
  _c = c
@@ -394,10 +409,11 @@ class Shell(cmd.Cmd):
394
409
  _c = colored(_c, **get_config('shell', 'ansi', 'prompt', 'rich'))
395
410
  remainder_prompt[i] = _c
396
411
  self.prompt = ''.join(remainder_prompt).replace(
397
- '{username}', self.username
412
+ '{username}', shell_attrs['username']
398
413
  ).replace(
399
- '{instance}', self.instance
414
+ '{instance}', shell_attrs['instance']
400
415
  )
416
+ shell_attrs['prompt'] = self.prompt
401
417
  ### flush stdout
402
418
  print("", end="", flush=True)
403
419
 
@@ -412,6 +428,9 @@ class Shell(cmd.Cmd):
412
428
  ### Preserve the working directory.
413
429
  old_cwd = os.getcwd()
414
430
 
431
+ from meerschaum._internal.entry import _shell, get_shell
432
+ self = get_shell(sysargs=shell_attrs['_sysargs'], debug=shell_attrs.get('debug', False))
433
+
415
434
  ### make a backup of line for later
416
435
  original_line = deepcopy(line)
417
436
 
@@ -427,7 +446,7 @@ class Shell(cmd.Cmd):
427
446
  ### if the user specifies, clear the screen before executing any commands
428
447
  if _clear_screen:
429
448
  from meerschaum.utils.formatting._shell import clear_screen
430
- clear_screen(debug=self.debug)
449
+ clear_screen(debug=shell_attrs['debug'])
431
450
 
432
451
  ### return blank commands (spaces break argparse)
433
452
  if original_line is None or len(str(line).strip()) == 0:
@@ -456,11 +475,10 @@ class Shell(cmd.Cmd):
456
475
  args['shell'] = True
457
476
  args['line'] = line
458
477
 
459
-
460
478
  ### if debug is not set on the command line,
461
479
  ### default to shell setting
462
480
  if not args.get('debug', False):
463
- args['debug'] = self.debug
481
+ args['debug'] = shell_attrs['debug']
464
482
 
465
483
  ### Make sure an action was provided.
466
484
  if not args.get('action', None):
@@ -479,17 +497,19 @@ class Shell(cmd.Cmd):
479
497
  from meerschaum.actions import get_main_action_name
480
498
  main_action_name = get_main_action_name(args['action'])
481
499
  if main_action_name is None:
482
- if not hasattr(self, 'do_'+args['action'][0]):
500
+ if not hasattr(self, 'do_' + args['action'][0]):
483
501
  args['action'].insert(0, 'sh')
484
502
  main_action_name = 'sh'
503
+ else:
504
+ main_action_name = args['action'][0]
485
505
 
486
506
  ### if no instance is provided, use current shell default,
487
507
  ### but not for the 'api' command (to avoid recursion)
488
508
  if 'mrsm_instance' not in args and main_action_name != 'api':
489
- args['mrsm_instance'] = str(self.instance_keys)
509
+ args['mrsm_instance'] = str(shell_attrs['instance_keys'])
490
510
 
491
511
  if 'repository' not in args and main_action_name != 'api':
492
- args['repository'] = str(self.repo_keys)
512
+ args['repository'] = str(shell_attrs['repo_keys'])
493
513
 
494
514
  ### parse out empty strings
495
515
  if args['action'][0].strip("\"'") == '':
@@ -501,21 +521,25 @@ class Shell(cmd.Cmd):
501
521
  args['action'] = ['start', 'jobs'] + args['action']
502
522
  main_action_name = 'start'
503
523
 
504
- positional_only = (main_action_name not in self._actions)
524
+ positional_only = (main_action_name not in shell_attrs['_actions'])
505
525
  if positional_only:
506
526
  return original_line
507
527
 
508
528
  from meerschaum._internal.entry import entry_with_args
509
529
 
510
530
  try:
511
- success_tuple = entry_with_args(_actions=self._actions, **args)
531
+ success_tuple = entry_with_args(_actions=shell_attrs['_actions'], **args)
532
+ # success_tuple = entry_with_args(**args)
512
533
  except Exception as e:
513
534
  success_tuple = False, str(e)
514
535
 
515
536
  from meerschaum.utils.formatting import print_tuple
516
537
  if isinstance(success_tuple, tuple):
517
538
  print_tuple(
518
- success_tuple, skip_common=(not self.debug), upper_padding=1, lower_padding=0,
539
+ success_tuple,
540
+ skip_common = (not shell_attrs['debug']),
541
+ upper_padding = 1,
542
+ lower_padding = 0,
519
543
  )
520
544
 
521
545
  ### Restore the old working directory.
@@ -525,9 +549,9 @@ class Shell(cmd.Cmd):
525
549
  return ""
526
550
 
527
551
  def postcmd(self, stop : bool = False, line : str = ""):
528
- _reload = self._reload
552
+ _reload = shell_attrs['_reload']
529
553
  if _reload:
530
- self.load_config(self.instance)
554
+ self.load_config(shell_attrs['instance'])
531
555
  if stop:
532
556
  return True
533
557
 
@@ -555,15 +579,15 @@ class Shell(cmd.Cmd):
555
579
  except (IndexError, AttributeError):
556
580
  state = ''
557
581
  if state == '':
558
- self.debug = not self.debug
582
+ shell_attrs['debug'] = not shell_attrs['debug']
559
583
  elif state.lower() in on_commands:
560
- self.debug = True
584
+ shell_attrs['debug'] = True
561
585
  elif state.lower() in off_commands:
562
- self.debug = False
586
+ shell_attrs['debug'] = False
563
587
  else:
564
588
  info(f"Unknown state '{state}'. Ignoring...")
565
589
 
566
- info(f"Debug mode is {'on' if self.debug else 'off'}.")
590
+ info(f"Debug mode is {'on' if shell_attrs['debug'] else 'off'}.")
567
591
 
568
592
  def do_instance(
569
593
  self,
@@ -619,7 +643,7 @@ class Shell(cmd.Cmd):
619
643
  else:
620
644
  conn_keys = instance_keys
621
645
 
622
- self.instance_keys = conn_keys
646
+ shell_attrs['instance_keys'] = conn_keys
623
647
 
624
648
  self.update_prompt(instance=conn_keys)
625
649
  info(f"Default instance for the current shell: {conn_keys}")
@@ -683,7 +707,7 @@ class Shell(cmd.Cmd):
683
707
  if conn is None or not conn:
684
708
  conn = get_connector('api', debug=debug)
685
709
 
686
- self.repo_keys = str(conn)
710
+ shell_attrs['repo_keys'] = str(conn)
687
711
 
688
712
  info(f"Default repository for the current shell: {conn}")
689
713
  return True, "Success"
@@ -712,9 +736,9 @@ class Shell(cmd.Cmd):
712
736
  args = parse_line(line)
713
737
  if len(args['action']) == 0:
714
738
  del args['action']
715
- self._actions['show'](['actions'], **args)
739
+ shell_attrs['_actions']['show'](['actions'], **args)
716
740
  return ""
717
- if args['action'][0] not in self._actions:
741
+ if args['action'][0] not in shell_attrs['_actions']:
718
742
  try:
719
743
  print(textwrap.dedent(getattr(self, f"do_{args['action'][0]}").__doc__))
720
744
  except Exception as e:
@@ -780,17 +804,21 @@ class Shell(cmd.Cmd):
780
804
  Patch builtin cmdloop with my own input (defined below).
781
805
  """
782
806
  import signal, os
783
- cmd.__builtins__['input'] = input_with_sigint(_old_input, self.session, shell=self)
807
+ cmd.__builtins__['input'] = input_with_sigint(
808
+ _old_input,
809
+ shell_attrs['session'],
810
+ shell = self,
811
+ )
784
812
 
785
813
  ### if the user specifies, clear the screen before initializing the shell
786
814
  if _clear_screen:
787
815
  from meerschaum.utils.formatting._shell import clear_screen
788
- clear_screen(debug=self.debug)
816
+ clear_screen(debug=shell_attrs['debug'])
789
817
 
790
818
  ### if sysargs are provided, skip printing the intro and execute instead
791
- if self._sysargs:
792
- self.intro = ""
793
- self.precmd(' '.join(self._sysargs))
819
+ if shell_attrs['_sysargs']:
820
+ shell_attrs['intro'] = ""
821
+ self.precmd(' '.join(shell_attrs['_sysargs']))
794
822
 
795
823
  def postloop(self):
796
824
  print('\n' + self.close_message)
@@ -816,24 +844,24 @@ def input_with_sigint(_input, session, shell: Optional[Shell] = None):
816
844
  nonlocal last_connected
817
845
  if not get_config('shell', 'bottom_toolbar', 'enabled'):
818
846
  return None
819
- if not shell._update_bottom_toolbar and platform.system() == 'Windows':
820
- return shell._old_bottom_toolbar
847
+ if not shell_attrs['_update_bottom_toolbar'] and platform.system() == 'Windows':
848
+ return shell_attrs['_old_bottom_toolbar']
821
849
  size = os.get_terminal_size()
822
850
  num_cols, num_lines = size.columns, size.lines
823
851
 
824
852
  instance_colored = (
825
853
  colored(
826
- shell.instance_keys, 'on ' + get_config(
854
+ shell_attrs['instance_keys'], 'on ' + get_config(
827
855
  'shell', 'ansi', 'instance', 'rich', 'style'
828
856
  )
829
- ) if ANSI else colored(shell.instance_keys, 'on white')
857
+ ) if ANSI else colored(shell_attrs['instance_keys'], 'on white')
830
858
  )
831
859
  repo_colored = (
832
- colored(shell.repo_keys, 'on ' + get_config('shell', 'ansi', 'repo', 'rich', 'style'))
833
- if ANSI else colored(shell.repo_keys, 'on white')
860
+ colored(shell_attrs['repo_keys'], 'on ' + get_config('shell', 'ansi', 'repo', 'rich', 'style'))
861
+ if ANSI else colored(shell_attrs['repo_keys'], 'on white')
834
862
  )
835
863
  try:
836
- typ, label = shell.instance_keys.split(':')
864
+ typ, label = shell_attrs['instance_keys'].split(':')
837
865
  connected = typ in connectors and label in connectors[typ]
838
866
  except Exception as e:
839
867
  connected = False
@@ -859,9 +887,9 @@ def input_with_sigint(_input, session, shell: Optional[Shell] = None):
859
887
  )
860
888
  buffer = (' ' * buffer_size) if buffer_size > 0 else '\n '
861
889
  text = left + buffer + right
862
- shell._old_bottom_toolbar = prompt_toolkit_formatted_text.ANSI(text)
863
- shell._update_bottom_toolbar = False
864
- return shell._old_bottom_toolbar
890
+ shell_attrs['_old_bottom_toolbar'] = prompt_toolkit_formatted_text.ANSI(text)
891
+ shell_attrs['_update_bottom_toolbar'] = False
892
+ return shell_attrs['_old_bottom_toolbar']
865
893
 
866
894
  def _patched_prompt(*args):
867
895
  _args = []
@@ -24,7 +24,9 @@ class ShellCompleter(Completer):
24
24
  """
25
25
  Bridge the built-in cmd completer with the `prompt_toolkit` completer system.
26
26
  """
27
- shell_actions = [a[3:] for a in dir(get_shell()) if a.startswith('do_')]
27
+ from meerschaum._internal.shell.Shell import shell_attrs
28
+ shell = get_shell()
29
+ shell_actions = [a[3:] for a in dir(shell) if a.startswith('do_')]
28
30
  yielded = []
29
31
  ensure_readline()
30
32
  parts = document.text.split('-')
@@ -32,7 +34,6 @@ class ShellCompleter(Completer):
32
34
  part_0_subbed_spaces = parts[0].replace(' ', '_')
33
35
  parsed_text = part_0_subbed_spaces + '-'.join(parts[1:])
34
36
 
35
- shell = get_shell()
36
37
 
37
38
  ### Index is the rank order (0 is closest match).
38
39
  ### Break when no results are returned.
@@ -50,11 +51,14 @@ class ShellCompleter(Completer):
50
51
  yielded.append(poss)
51
52
 
52
53
  args = parse_line(document.text)
53
- action_function = get_action(args['action'], _actions=shell._actions)
54
+ action_function = get_action(args['action'], _actions=shell_attrs.get('_actions', None))
54
55
  if action_function is None:
55
56
  return
56
57
 
57
- main_action_name = get_main_action_name(args['action'], _actions=shell._actions)
58
+ main_action_name = get_main_action_name(
59
+ args['action'],
60
+ _actions = shell_attrs.get('_actions', None)
61
+ )
58
62
 
59
63
  ### If we haven't yet hit space, don't suggest subactions.
60
64
  if not parsed_text.replace(
@@ -291,7 +291,6 @@ __all__ = ['actions', 'get_subactions', 'get_action', 'get_main_action_name', 'g
291
291
  ### functions that do not begin with '_' from all submodules.
292
292
  from inspect import getmembers, isfunction
293
293
  actions = {}
294
- "This docstring will be replaced in __pdoc__ at the end of this file."
295
294
 
296
295
  for module in modules:
297
296
  ### A couple important things happening here:
@@ -324,6 +323,8 @@ original_actions = actions.copy()
324
323
  from meerschaum._internal.entry import entry, get_shell
325
324
  import meerschaum.plugins
326
325
  make_action = meerschaum.plugins.make_action
326
+ pre_sync_hook = meerschaum.plugins.pre_sync_hook
327
+ post_sync_hook = meerschaum.plugins.post_sync_hook
327
328
 
328
329
  ### Instruct pdoc to skip the `meerschaum.actions.plugins` subdirectory.
329
330
  __pdoc__ = {
@@ -17,8 +17,5 @@ def reload(
17
17
  """
18
18
  Reload the running Meerschaum instance.
19
19
  """
20
- from meerschaum.utils.packages import reload_package
21
- from meerschaum.plugins import reload_plugins
22
- reload_package('meerschaum')
23
- reload_plugins(debug=debug)
24
- return True, "Success"
20
+ from meerschaum.utils.packages import reload_meerschaum
21
+ return reload_meerschaum(debug=debug)