meerschaum 2.3.5.dev0__py3-none-any.whl → 2.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. meerschaum/_internal/arguments/__init__.py +2 -1
  2. meerschaum/_internal/arguments/_parse_arguments.py +88 -12
  3. meerschaum/_internal/docs/index.py +3 -2
  4. meerschaum/_internal/entry.py +42 -20
  5. meerschaum/_internal/shell/Shell.py +38 -44
  6. meerschaum/_internal/term/TermPageHandler.py +2 -3
  7. meerschaum/_internal/term/__init__.py +13 -11
  8. meerschaum/actions/api.py +26 -23
  9. meerschaum/actions/bootstrap.py +38 -11
  10. meerschaum/actions/copy.py +3 -3
  11. meerschaum/actions/delete.py +4 -1
  12. meerschaum/actions/register.py +1 -3
  13. meerschaum/actions/stack.py +24 -19
  14. meerschaum/actions/start.py +41 -41
  15. meerschaum/actions/sync.py +53 -52
  16. meerschaum/api/__init__.py +48 -14
  17. meerschaum/api/_events.py +26 -17
  18. meerschaum/api/_oauth2.py +2 -2
  19. meerschaum/api/_websockets.py +5 -4
  20. meerschaum/api/dash/__init__.py +7 -16
  21. meerschaum/api/dash/callbacks/__init__.py +1 -0
  22. meerschaum/api/dash/callbacks/dashboard.py +52 -58
  23. meerschaum/api/dash/callbacks/jobs.py +15 -16
  24. meerschaum/api/dash/callbacks/login.py +16 -10
  25. meerschaum/api/dash/callbacks/pipes.py +41 -0
  26. meerschaum/api/dash/callbacks/plugins.py +1 -1
  27. meerschaum/api/dash/callbacks/register.py +15 -11
  28. meerschaum/api/dash/components.py +54 -59
  29. meerschaum/api/dash/jobs.py +5 -9
  30. meerschaum/api/dash/pages/__init__.py +1 -0
  31. meerschaum/api/dash/pages/pipes.py +19 -0
  32. meerschaum/api/dash/pipes.py +86 -58
  33. meerschaum/api/dash/plugins.py +6 -4
  34. meerschaum/api/dash/sessions.py +176 -0
  35. meerschaum/api/dash/users.py +3 -41
  36. meerschaum/api/dash/webterm.py +12 -17
  37. meerschaum/api/resources/static/js/terminado.js +1 -1
  38. meerschaum/api/routes/_actions.py +4 -118
  39. meerschaum/api/routes/_jobs.py +45 -24
  40. meerschaum/api/routes/_login.py +4 -4
  41. meerschaum/api/routes/_pipes.py +3 -3
  42. meerschaum/api/routes/_webterm.py +5 -6
  43. meerschaum/config/_default.py +15 -3
  44. meerschaum/config/_version.py +1 -1
  45. meerschaum/config/stack/__init__.py +64 -21
  46. meerschaum/config/static/__init__.py +6 -0
  47. meerschaum/connectors/{Connector.py → _Connector.py} +19 -13
  48. meerschaum/connectors/__init__.py +24 -14
  49. meerschaum/connectors/api/{APIConnector.py → _APIConnector.py} +3 -1
  50. meerschaum/connectors/api/__init__.py +2 -1
  51. meerschaum/connectors/api/_actions.py +22 -36
  52. meerschaum/connectors/api/_jobs.py +1 -0
  53. meerschaum/connectors/parse.py +18 -16
  54. meerschaum/connectors/poll.py +30 -24
  55. meerschaum/connectors/sql/__init__.py +3 -1
  56. meerschaum/connectors/sql/_pipes.py +172 -197
  57. meerschaum/connectors/sql/_plugins.py +45 -43
  58. meerschaum/connectors/sql/_users.py +46 -38
  59. meerschaum/connectors/valkey/_ValkeyConnector.py +535 -0
  60. meerschaum/connectors/valkey/__init__.py +10 -0
  61. meerschaum/connectors/valkey/_fetch.py +75 -0
  62. meerschaum/connectors/valkey/_pipes.py +844 -0
  63. meerschaum/connectors/valkey/_plugins.py +265 -0
  64. meerschaum/connectors/valkey/_users.py +305 -0
  65. meerschaum/core/Pipe/__init__.py +3 -0
  66. meerschaum/core/Pipe/_attributes.py +1 -2
  67. meerschaum/core/Pipe/_clear.py +16 -13
  68. meerschaum/core/Pipe/_copy.py +106 -0
  69. meerschaum/core/Pipe/_data.py +165 -101
  70. meerschaum/core/Pipe/_drop.py +4 -4
  71. meerschaum/core/Pipe/_dtypes.py +14 -14
  72. meerschaum/core/Pipe/_edit.py +15 -14
  73. meerschaum/core/Pipe/_sync.py +134 -53
  74. meerschaum/core/Pipe/_verify.py +11 -11
  75. meerschaum/core/User/_User.py +14 -12
  76. meerschaum/jobs/_Job.py +27 -14
  77. meerschaum/jobs/__init__.py +7 -2
  78. meerschaum/jobs/systemd.py +20 -8
  79. meerschaum/plugins/_Plugin.py +17 -13
  80. meerschaum/utils/_get_pipes.py +14 -20
  81. meerschaum/utils/dataframe.py +291 -101
  82. meerschaum/utils/dtypes/__init__.py +31 -6
  83. meerschaum/utils/dtypes/sql.py +4 -4
  84. meerschaum/utils/formatting/_shell.py +5 -6
  85. meerschaum/utils/misc.py +3 -3
  86. meerschaum/utils/packages/__init__.py +14 -9
  87. meerschaum/utils/packages/_packages.py +2 -0
  88. meerschaum/utils/prompt.py +1 -1
  89. meerschaum/utils/schedule.py +1 -0
  90. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/METADATA +7 -1
  91. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/RECORD +98 -89
  92. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/WHEEL +1 -1
  93. meerschaum/api/dash/actions.py +0 -255
  94. /meerschaum/connectors/sql/{SQLConnector.py → _SQLConnector.py} +0 -0
  95. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/LICENSE +0 -0
  96. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/NOTICE +0 -0
  97. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/entry_points.txt +0 -0
  98. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/top_level.txt +0 -0
  99. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dist-info}/zip-safe +0 -0
@@ -234,7 +234,13 @@ def _bootstrap_connectors(
234
234
  Prompt the user for the details necessary to create a Connector.
235
235
  """
236
236
  from meerschaum.connectors.parse import is_valid_connector_keys
237
- from meerschaum.connectors import connectors, get_connector, types, custom_types
237
+ from meerschaum.connectors import (
238
+ connectors,
239
+ get_connector,
240
+ types,
241
+ custom_types,
242
+ _load_builtin_custom_connectors,
243
+ )
238
244
  from meerschaum.utils.prompt import prompt, yes_no, choose
239
245
  from meerschaum.config import get_config
240
246
  from meerschaum.config._edit import write_config
@@ -246,6 +252,7 @@ def _bootstrap_connectors(
246
252
 
247
253
  abort_tuple = False, "No connectors bootstrapped."
248
254
  _clear = get_config('shell', 'clear_screen', patch=True)
255
+ _load_builtin_custom_connectors()
249
256
 
250
257
  if action is None:
251
258
  action = []
@@ -262,8 +269,8 @@ def _bootstrap_connectors(
262
269
  + ' See https://meerschaum.io/reference/connectors '
263
270
  + 'for documentation on connectors.\n'
264
271
  ),
265
- sorted(list(connectors)),
266
- default = 'sql'
272
+ sorted([k for k in connectors if k != 'plugin']),
273
+ default='sql',
267
274
  )
268
275
  except KeyboardInterrupt:
269
276
  return abort_tuple
@@ -288,21 +295,30 @@ def _bootstrap_connectors(
288
295
  warn(f"Connector '{_type}:{_label}' already exists.", stack=False)
289
296
  overwrite = yes_no(
290
297
  f"Do you want to overwrite connector '{_type}:{_label}'?",
291
- default = 'n',
292
- yes = yes,
293
- noask = noask,
298
+ default='n',
299
+ yes=yes,
300
+ noask=noask,
294
301
  )
295
302
  if not overwrite and not force:
296
- return False, f"No changes made to connector configuration."
297
- break
303
+ return False, "No changes made to connector configuration."
304
+ break
298
305
  elif _label == "":
299
- warn(f"Please enter a label.", stack=False)
306
+ warn("Please enter a label.", stack=False)
300
307
  else:
301
308
  break
302
309
 
303
310
  cls = types.get(_type)
304
311
  cls_required_attrs = getattr(cls, 'REQUIRED_ATTRIBUTES', [])
305
- type_attributes = connector_attributes.get(_type, {'required': cls_required_attrs})
312
+ cls_optional_attrs = getattr(cls, 'OPTIONAL_ATTRIBUTES', [])
313
+ cls_default_attrs = getattr(cls, 'DEFAULT_ATTRIBUTES', {})
314
+ type_attributes = connector_attributes.get(
315
+ _type,
316
+ {
317
+ 'required': cls_required_attrs,
318
+ 'optional': cls_optional_attrs,
319
+ 'default': cls_default_attrs,
320
+ }
321
+ )
306
322
 
307
323
  new_attributes = {}
308
324
  if 'flavors' in type_attributes:
@@ -320,9 +336,11 @@ def _bootstrap_connectors(
320
336
  return abort_tuple
321
337
  new_attributes['flavor'] = flavor
322
338
  required = sorted(list(connector_attributes[_type]['flavors'][flavor]['requirements']))
339
+ required = sorted(list(connector_attributes[_type]['flavors'][flavor]['optional']))
323
340
  default = type_attributes['flavors'][flavor].get('defaults', {})
324
341
  else:
325
342
  required = sorted(list(type_attributes.get('required', {})))
343
+ optional = sorted(list(type_attributes.get('optional', {})))
326
344
  default = type_attributes.get('default', {})
327
345
  info(
328
346
  f"Please answer the following questions to configure the new connector '{_type}:{_label}'."
@@ -330,13 +348,22 @@ def _bootstrap_connectors(
330
348
  )
331
349
  for r in required:
332
350
  try:
333
- val = prompt(f"Value for {r}:")
351
+ default_val = str(default.get(r)) if r in default else None
352
+ val = prompt(f"Value for {r}:", default=default_val)
334
353
  except KeyboardInterrupt:
335
354
  continue
336
355
  if is_int(val):
337
356
  val = int(val)
338
357
  new_attributes[r] = val
339
358
 
359
+ for o in optional:
360
+ try:
361
+ val = prompt(f"Value for {o} (optional; empty to omit):")
362
+ except KeyboardInterrupt:
363
+ continue
364
+ if val:
365
+ new_attributes[o] = val
366
+
340
367
  for k, v in default.items():
341
368
  ### skip already configured attributes, (e.g. flavor or from required)
342
369
  if k in new_attributes:
@@ -115,11 +115,11 @@ def _copy_pipes(
115
115
  ):
116
116
  _new_pipe.sync(
117
117
  p.get_data(
118
- debug = debug,
119
- as_iterator = True,
118
+ debug=debug,
119
+ as_iterator=True,
120
120
  **kw
121
121
  ),
122
- debug = debug,
122
+ debug=debug,
123
123
  **kw
124
124
  )
125
125
 
@@ -521,7 +521,10 @@ def _complete_delete_jobs(
521
521
  )
522
522
  )
523
523
 
524
- if parse_executor_keys(executor_keys, construct=False) is None:
524
+ if (
525
+ executor_keys != 'systemd'
526
+ and parse_executor_keys(executor_keys, construct=False) is None
527
+ ):
525
528
  return []
526
529
 
527
530
  jobs = get_jobs(executor_keys, include_hidden=False)
@@ -118,7 +118,6 @@ def _register_pipes(
118
118
  )
119
119
 
120
120
  success, message = True, "Success"
121
- failed_message = ""
122
121
  failed_pipes = []
123
122
  success_pipes = []
124
123
  for p in pipes:
@@ -127,7 +126,6 @@ def _register_pipes(
127
126
  ss, msg = p.register(debug=debug)
128
127
  if not ss:
129
128
  warn(f"{msg}", stack=False)
130
- success = False
131
129
  failed_pipes.append(p)
132
130
  else:
133
131
  success_pipes.append(p)
@@ -356,7 +354,7 @@ def _register_users(
356
354
 
357
355
  msg = (
358
356
  f"Finished registering {succeeded + failed} users." + '\n' +
359
- f" ({succeeded} succeeded, {failed} failed)"
357
+ f" ({succeeded} succeeded, {failed} failed)"
360
358
  )
361
359
  return succeeded > 0, msg
362
360
 
@@ -9,34 +9,32 @@ Functions for running the Docker Compose stack
9
9
  from __future__ import annotations
10
10
  from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Union
11
11
 
12
+
12
13
  def stack(
13
- action: Optional[List[str]] = None,
14
- sysargs: Optional[List[str]] = None,
15
- sub_args: Optional[List[str]] = None,
16
- yes: bool = False,
17
- noask: bool = False,
18
- force: bool = False,
19
- debug: bool = False,
20
- _capture_output: bool = False,
21
- **kw: Any
22
- ) -> Union[SuccessTuple, 'subprocess.Popen']:
14
+ action: Optional[List[str]] = None,
15
+ sysargs: Optional[List[str]] = None,
16
+ sub_args: Optional[List[str]] = None,
17
+ yes: bool = False,
18
+ noask: bool = False,
19
+ force: bool = False,
20
+ debug: bool = False,
21
+ _capture_output: bool = False,
22
+ **kw: Any
23
+ ) -> Union[SuccessTuple, 'subprocess.Popen']:
23
24
  """
24
25
  Control the Meerschaum stack with Docker Compose.
25
26
  Usage: `stack {command}`
26
-
27
+
27
28
  Command: action[0]: default 'up'
28
29
  Docker Compose command to run. E.g. 'config' will print Docker Compose configuration
29
30
  """
30
31
  import subprocess
31
- import contextlib
32
- import io
33
32
  import os
34
33
  import sys
35
34
  import pathlib
36
35
  import meerschaum.config.stack
37
36
  from meerschaum.config.stack import NECESSARY_FILES, write_stack
38
37
  from meerschaum.config._paths import STACK_COMPOSE_PATH
39
- from meerschaum.utils.prompt import yes_no
40
38
  import meerschaum.config
41
39
  from meerschaum.config._patch import apply_patch_to_config
42
40
  from meerschaum.utils.packages import (
@@ -47,9 +45,9 @@ def stack(
47
45
  from meerschaum.config import get_config
48
46
  from meerschaum.utils.debug import dprint
49
47
  from meerschaum.utils.warnings import warn
50
- from meerschaum.utils.formatting import ANSI
51
48
  from meerschaum.utils.misc import is_docker_available
52
49
  from meerschaum.config._read_config import search_and_substitute_config
50
+ from meerschaum.utils.prompt import yes_no
53
51
 
54
52
  stack_env_dict = apply_patch_to_config(
55
53
  os.environ.copy(),
@@ -81,7 +79,7 @@ def stack(
81
79
  break
82
80
  if bootstrap:
83
81
  write_stack(debug=debug)
84
- else:
82
+ else:
85
83
  sync_files(['stack'])
86
84
 
87
85
  ### define project name when starting containers
@@ -91,7 +89,7 @@ def stack(
91
89
  'stack', 'project_name', patch=True, substitute=True,
92
90
  )
93
91
  ]
94
-
92
+
95
93
  ### Debug list used to include --log-level DEBUG, but the flag is not supported on Windows (?)
96
94
  debug_list = []
97
95
 
@@ -102,7 +100,7 @@ def stack(
102
100
  print(
103
101
  "To start the Docker service, run `sudo systemctl start docker` or `sudo dockerd`.\n"
104
102
  + "On Windows or MacOS, make sure Docker Desktop is running.",
105
- file = sys.stderr,
103
+ file=sys.stderr,
106
104
  )
107
105
  return False, "Failed to connect to the Docker engine."
108
106
 
@@ -115,7 +113,7 @@ def stack(
115
113
 
116
114
  if not has_builtin_compose:
117
115
  _compose_venv = 'mrsm'
118
- compose = attempt_import('compose', lazy=False, venv=_compose_venv, debug=debug)
116
+ _ = attempt_import('compose', lazy=False, venv=_compose_venv, debug=debug)
119
117
 
120
118
  ### If docker-compose is installed globally, don't use the `mrsm` venv.
121
119
  if not venv_contains_package('compose', _compose_venv):
@@ -129,6 +127,13 @@ def stack(
129
127
  if not pip_install('pyyaml', venv=_compose_venv, debug=debug):
130
128
  warn(f"Unable to install `pyyaml` into venv '{_compose_venv}'.")
131
129
 
130
+ if 'down' in sysargs and '-v' in sysargs:
131
+ if not yes_no(
132
+ "Are you sure you want to drop volumes?\n This cannot be undone!",
133
+ default='n',
134
+ ):
135
+ return False, "Nothing was dropped."
136
+
132
137
  cmd_list = [
133
138
  _arg
134
139
  for _arg in (settings_list + sysargs[1:])
@@ -89,6 +89,7 @@ def _start_jobs(
89
89
  name: Optional[str] = None,
90
90
  sysargs: Optional[List[str]] = None,
91
91
  executor_keys: Optional[str] = None,
92
+ rm: bool = False,
92
93
  debug: bool = False,
93
94
  **kw
94
95
  ) -> SuccessTuple:
@@ -210,7 +211,7 @@ def _start_jobs(
210
211
 
211
212
  def _run_new_job(name: Optional[str] = None):
212
213
  name = name or get_new_daemon_name()
213
- job = Job(name, sysargs, executor_keys=executor_keys)
214
+ job = Job(name, sysargs, executor_keys=executor_keys, delete_after_completion=rm)
214
215
  return job.start(debug=debug), name
215
216
 
216
217
  def _run_existing_job(name: str):
@@ -303,24 +304,20 @@ def _start_jobs(
303
304
 
304
305
 
305
306
  def _start_gui(
306
- action: Optional[List[str]] = None,
307
- mrsm_instance: Optional[str] = None,
308
- port: Optional[int] = None,
309
- debug: bool = False,
310
- **kw
311
- ) -> SuccessTuple:
307
+ action: Optional[List[str]] = None,
308
+ mrsm_instance: Optional[str] = None,
309
+ port: Optional[int] = None,
310
+ debug: bool = False,
311
+ **kw
312
+ ) -> SuccessTuple:
312
313
  """
313
314
  Start the Meerschaum GUI application.
314
315
  """
315
- from meerschaum.utils.daemon import Daemon
316
- from meerschaum.utils.process import run_process
317
316
  from meerschaum.utils.venv import venv_exec
318
- from meerschaum.utils.packages import (
319
- run_python_package, attempt_import, venv_contains_package, pip_install
320
- )
317
+ from meerschaum.utils.packages import attempt_import
321
318
  from meerschaum.utils.warnings import warn
322
319
  from meerschaum.utils.debug import dprint
323
- from meerschaum.utils.networking import find_open_ports, is_port_in_use
320
+ from meerschaum.utils.networking import find_open_ports
324
321
  from meerschaum.connectors.parse import parse_instance_keys
325
322
  from meerschaum._internal.term.tools import is_webterm_running
326
323
  import platform
@@ -394,13 +391,14 @@ def _start_gui(
394
391
 
395
392
 
396
393
  def _start_webterm(
397
- port: Optional[int] = None,
398
- host: Optional[str] = None,
399
- force: bool = False,
400
- nopretty: bool = False,
401
- sysargs: Optional[List[str]] = None,
402
- **kw
403
- ) -> SuccessTuple:
394
+ port: Optional[int] = None,
395
+ host: Optional[str] = None,
396
+ mrsm_instance: Optional[str] = None,
397
+ force: bool = False,
398
+ nopretty: bool = False,
399
+ sysargs: Optional[List[str]] = None,
400
+ **kw
401
+ ) -> SuccessTuple:
404
402
  """
405
403
  Start the Meerschaum Web Terminal.
406
404
 
@@ -408,15 +406,17 @@ def _start_webterm(
408
406
  - `-p`, `--port`
409
407
  The port to which the webterm binds.
410
408
  Defaults to 8765, and `--force` will choose the next available port.
411
-
409
+
412
410
  - `--host`
413
411
  The host interface to which the webterm binds.
414
412
  Defaults to '127.0.0.1'.
413
+
414
+ - `-i`, '--instance'
415
+ The default instance to use for the Webterm shell.
415
416
  """
416
- from meerschaum._internal.term import get_webterm_app_and_manager, tornado, tornado_ioloop
417
+ from meerschaum._internal.term import get_webterm_app_and_manager, tornado_ioloop
417
418
  from meerschaum._internal.term.tools import is_webterm_running
418
- from meerschaum.utils.networking import find_open_ports, is_port_in_use
419
- from meerschaum.utils.packages import attempt_import
419
+ from meerschaum.utils.networking import find_open_ports
420
420
  from meerschaum.utils.warnings import info
421
421
 
422
422
  if host is None:
@@ -425,7 +425,7 @@ def _start_webterm(
425
425
  port = 8765
426
426
  if sysargs is None:
427
427
  sysargs = ['start', 'webterm']
428
- tornado_app, term_manager = get_webterm_app_and_manager()
428
+ tornado_app, term_manager = get_webterm_app_and_manager(instance_keys=mrsm_instance)
429
429
 
430
430
  if is_webterm_running(host, port):
431
431
  if force:
@@ -454,12 +454,12 @@ def _start_webterm(
454
454
 
455
455
 
456
456
  def _start_connectors(
457
- action: Optional[List[str]] = None,
458
- connector_keys: Optional[List[str]] = None,
459
- min_seconds: int = 3,
460
- debug: bool = False,
461
- **kw
462
- ) -> SuccessTuple:
457
+ action: Optional[List[str]] = None,
458
+ connector_keys: Optional[List[str]] = None,
459
+ min_seconds: int = 3,
460
+ debug: bool = False,
461
+ **kw
462
+ ) -> SuccessTuple:
463
463
  """
464
464
  Start polling connectors to verify a connection can be made.
465
465
  """
@@ -479,7 +479,7 @@ def _start_connectors(
479
479
  for keys in unique_keys:
480
480
  try:
481
481
  conn = parse_instance_keys(keys)
482
- except Exception as e:
482
+ except Exception:
483
483
  warn(f"Invalid connector keys: '{keys}'. Skipping...", stack=False)
484
484
  continue
485
485
  valid_conns.append(conn)
@@ -487,20 +487,19 @@ def _start_connectors(
487
487
  if not valid_conns:
488
488
  return False, "No valid connector keys were provided."
489
489
 
490
-
491
490
  connected = {}
492
491
  def connect(conn):
493
492
  success = retry_connect(
494
493
  conn,
495
- retry_wait = min_seconds,
496
- enforce_chaining = False,
497
- enforce_login = False,
498
- print_on_connect = True,
499
- debug = debug,
494
+ retry_wait=min_seconds,
495
+ enforce_chaining=False,
496
+ enforce_login=False,
497
+ print_on_connect=True,
498
+ debug=debug,
500
499
  )
501
500
  connected[conn] = success
502
501
  return success
503
-
502
+
504
503
  pool = get_pool()
505
504
  try:
506
505
  pool.map(connect, valid_conns)
@@ -517,12 +516,12 @@ def _start_connectors(
517
516
 
518
517
  success = len(fails) == 0
519
518
  msg = (
520
- f"Successfully started connector" + ('s' if len(successes) != 1 else '')
519
+ "Successfully started connector" + ('s' if len(successes) != 1 else '')
521
520
  + ' ' + items_str(successes) + '.'
522
521
  ) if success else f"Failed to start {len(fails)} connectors."
523
522
  if len(fails) > 0:
524
523
  msg += (
525
- f"\n Failed to start connector" + ('s' if len(fails) != 1 else '')
524
+ "\n Failed to start connector" + ('s' if len(fails) != 1 else '')
526
525
  + ' ' + items_str(fails) + '.'
527
526
  )
528
527
 
@@ -568,6 +567,7 @@ def _start_pipeline(
568
567
  else 1
569
568
  )
570
569
 
570
+ params = params or {}
571
571
  sub_args_line = params.get('sub_args_line', None)
572
572
  patch_args = params.get('patch_args', None)
573
573
 
@@ -9,10 +9,12 @@ NOTE: `sync` required a SQL connection and is not intended for client use
9
9
  """
10
10
 
11
11
  from __future__ import annotations
12
- from datetime import timedelta, datetime, timezone
12
+ from datetime import timedelta
13
+
13
14
  import meerschaum as mrsm
14
15
  from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Tuple, Union
15
16
 
17
+
16
18
  def sync(
17
19
  action: Optional[List[str]] = None,
18
20
  **kw: Any
@@ -38,47 +40,45 @@ def sync(
38
40
 
39
41
 
40
42
  def _pipes_lap(
41
- workers: Optional[int] = None,
42
- debug: Optional[bool] = None,
43
- unblock: bool = False,
44
- force: bool = False,
45
- min_seconds: int = 1,
46
- verify: bool = False,
47
- deduplicate: bool = False,
48
- bounded: Optional[bool] = None,
49
- chunk_interval: Union[timedelta, int, None] = None,
50
- mrsm_instance: Optional[str] = None,
51
- timeout_seconds: Optional[int] = None,
52
- nopretty: bool = False,
53
- _progress: Optional['rich.progress.Progress'] = None,
54
- **kw: Any
55
- ) -> Tuple[List[mrsm.Pipe], List[mrsm.Pipe]]:
43
+ workers: Optional[int] = None,
44
+ debug: Optional[bool] = None,
45
+ unblock: bool = False,
46
+ force: bool = False,
47
+ min_seconds: int = 1,
48
+ verify: bool = False,
49
+ deduplicate: bool = False,
50
+ bounded: Optional[bool] = None,
51
+ chunk_interval: Union[timedelta, int, None] = None,
52
+ mrsm_instance: Optional[str] = None,
53
+ timeout_seconds: Optional[int] = None,
54
+ nopretty: bool = False,
55
+ _progress: Optional['rich.progress.Progress'] = None,
56
+ **kw: Any
57
+ ) -> Tuple[List[mrsm.Pipe], List[mrsm.Pipe]]:
56
58
  """
57
59
  Do a lap of syncing pipes.
58
60
  """
61
+ import queue
62
+ import multiprocessing
63
+ import time
64
+ import copy
65
+ import json
66
+ import sys
67
+
59
68
  from meerschaum import get_pipes
60
69
  from meerschaum.utils.debug import dprint, _checkpoint
61
- from meerschaum.utils.packages import attempt_import, import_rich
62
- from meerschaum.utils.formatting import print_tuple, ANSI, UNICODE, get_console
70
+ from meerschaum.utils.packages import attempt_import
71
+ from meerschaum.utils.formatting import print_tuple
63
72
  from meerschaum.utils.warnings import warn
64
- from meerschaum.utils.threading import Lock, RLock, Thread, Event
65
- from meerschaum.utils.misc import print_options, get_cols_lines
66
- from meerschaum.utils.pool import get_pool_executor, get_pool
73
+ from meerschaum.utils.threading import Lock, Thread, Event
67
74
  from meerschaum.connectors.parse import parse_instance_keys
68
- from meerschaum import Plugin
69
- import queue
70
- import multiprocessing
71
- import contextlib
72
- import time, os, copy
73
75
  from meerschaum.utils.packages import venv_exec
74
76
  from meerschaum.utils.process import poll_process
75
- import json
76
- import sys
77
77
  dill = attempt_import('dill')
78
78
 
79
79
  rich_table, rich_text, rich_box = attempt_import(
80
80
  'rich.table', 'rich.text', 'rich.box',
81
- lazy = False,
81
+ lazy=False,
82
82
  )
83
83
  all_kw = copy.deepcopy(kw)
84
84
  all_kw.update({
@@ -126,7 +126,7 @@ def _pipes_lap(
126
126
  + "may lead to concurrency issues.\n You can change the pool size with "
127
127
  + "`edit config system` under the keys connectors:sql:create_engine:pool_size,\n "
128
128
  + "and a size of 0 will not limit the number of connections.",
129
- stack = False,
129
+ stack=False,
130
130
  )
131
131
 
132
132
 
@@ -155,8 +155,8 @@ def _pipes_lap(
155
155
  ) + msg + '\n'
156
156
  print_tuple(
157
157
  (success, msg),
158
- calm = True,
159
- _progress = _progress,
158
+ calm=True,
159
+ _progress=_progress,
160
160
  )
161
161
  _checkpoint(_progress=_progress, _task=_task)
162
162
  if _progress is not None:
@@ -274,25 +274,26 @@ def _sync_pipes(
274
274
  - `--debug`
275
275
  - Print verbose messages.
276
276
  """
277
- from meerschaum.utils.debug import dprint
277
+ import time
278
+ import os
279
+ import contextlib
280
+
278
281
  from meerschaum.utils.warnings import warn, info
279
- from meerschaum.utils.formatting import UNICODE
280
- from meerschaum.utils.formatting._shell import progress, live
281
- from meerschaum.utils.formatting._shell import clear_screen, flush_with_newlines
282
+ from meerschaum.utils.formatting._shell import progress
283
+ from meerschaum.utils.formatting._shell import clear_screen
282
284
  from meerschaum.utils.formatting import print_pipes_results
283
- import contextlib
284
- import time
285
- import sys
286
- import json
287
- import asyncio
285
+ from meerschaum.config.static import STATIC_CONFIG
286
+
287
+ noninteractive_val = os.environ.get(STATIC_CONFIG['environment']['noninteractive'], None)
288
+ is_noninterative = noninteractive_val in ('1', 'true', 'True', 'yes')
289
+
288
290
  run = True
289
291
  msg = ""
290
292
  interrupt_warning_msg = "Syncing was interrupted due to a keyboard interrupt."
291
293
  cooldown = 2 * (min_seconds + 1)
292
- underline = '\u2015' if UNICODE else '-'
293
294
  success_pipes, failure_pipes = [], []
294
295
  while run:
295
- _progress = progress() if shell else None
296
+ _progress = progress() if shell and not is_noninterative else None
296
297
  cm = _progress if _progress is not None else contextlib.nullcontext()
297
298
 
298
299
  lap_begin = time.perf_counter()
@@ -301,15 +302,15 @@ def _sync_pipes(
301
302
  results_dict = {}
302
303
  with cm:
303
304
  results_dict = _pipes_lap(
304
- min_seconds = min_seconds,
305
- _progress = _progress,
306
- verify = verify,
307
- deduplicate = deduplicate,
308
- bounded = bounded,
309
- chunk_interval = chunk_interval,
310
- unblock = unblock,
311
- debug = debug,
312
- nopretty = nopretty,
305
+ min_seconds=min_seconds,
306
+ _progress=_progress,
307
+ verify=verify,
308
+ deduplicate=deduplicate,
309
+ bounded=bounded,
310
+ chunk_interval=chunk_interval,
311
+ unblock=unblock,
312
+ debug=debug,
313
+ nopretty=nopretty,
313
314
  **kw
314
315
  )
315
316
  success_pipes = [