meerschaum 2.9.5__py3-none-any.whl → 3.0.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 (200) hide show
  1. meerschaum/__init__.py +5 -2
  2. meerschaum/_internal/__init__.py +1 -0
  3. meerschaum/_internal/arguments/_parse_arguments.py +4 -4
  4. meerschaum/_internal/arguments/_parser.py +33 -4
  5. meerschaum/_internal/cli/__init__.py +6 -0
  6. meerschaum/_internal/cli/daemons.py +103 -0
  7. meerschaum/_internal/cli/entry.py +220 -0
  8. meerschaum/_internal/cli/workers.py +435 -0
  9. meerschaum/_internal/docs/index.py +48 -2
  10. meerschaum/_internal/entry.py +50 -14
  11. meerschaum/_internal/shell/Shell.py +121 -29
  12. meerschaum/_internal/shell/__init__.py +4 -1
  13. meerschaum/_internal/static.py +359 -0
  14. meerschaum/_internal/term/TermPageHandler.py +1 -2
  15. meerschaum/_internal/term/__init__.py +40 -6
  16. meerschaum/_internal/term/tools.py +33 -8
  17. meerschaum/actions/__init__.py +6 -4
  18. meerschaum/actions/api.py +53 -13
  19. meerschaum/actions/attach.py +1 -0
  20. meerschaum/actions/bootstrap.py +8 -8
  21. meerschaum/actions/delete.py +4 -2
  22. meerschaum/actions/edit.py +171 -25
  23. meerschaum/actions/login.py +8 -8
  24. meerschaum/actions/register.py +143 -6
  25. meerschaum/actions/reload.py +22 -5
  26. meerschaum/actions/restart.py +14 -0
  27. meerschaum/actions/show.py +184 -31
  28. meerschaum/actions/start.py +166 -17
  29. meerschaum/actions/stop.py +38 -2
  30. meerschaum/actions/sync.py +7 -2
  31. meerschaum/actions/tag.py +9 -8
  32. meerschaum/actions/verify.py +5 -8
  33. meerschaum/api/__init__.py +45 -15
  34. meerschaum/api/_events.py +46 -4
  35. meerschaum/api/_oauth2.py +162 -9
  36. meerschaum/api/_tokens.py +102 -0
  37. meerschaum/api/dash/__init__.py +0 -3
  38. meerschaum/api/dash/callbacks/__init__.py +1 -0
  39. meerschaum/api/dash/callbacks/custom.py +4 -3
  40. meerschaum/api/dash/callbacks/dashboard.py +198 -118
  41. meerschaum/api/dash/callbacks/jobs.py +14 -7
  42. meerschaum/api/dash/callbacks/login.py +10 -1
  43. meerschaum/api/dash/callbacks/pipes.py +194 -14
  44. meerschaum/api/dash/callbacks/plugins.py +0 -1
  45. meerschaum/api/dash/callbacks/register.py +10 -3
  46. meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
  47. meerschaum/api/dash/callbacks/tokens.py +389 -0
  48. meerschaum/api/dash/components.py +36 -15
  49. meerschaum/api/dash/jobs.py +1 -1
  50. meerschaum/api/dash/keys.py +35 -93
  51. meerschaum/api/dash/pages/__init__.py +2 -1
  52. meerschaum/api/dash/pages/dashboard.py +1 -20
  53. meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
  54. meerschaum/api/dash/pages/login.py +2 -2
  55. meerschaum/api/dash/pages/pipes.py +16 -5
  56. meerschaum/api/dash/pages/settings/password_reset.py +1 -1
  57. meerschaum/api/dash/pages/tokens.py +53 -0
  58. meerschaum/api/dash/pipes.py +382 -95
  59. meerschaum/api/dash/sessions.py +12 -0
  60. meerschaum/api/dash/tokens.py +603 -0
  61. meerschaum/api/dash/websockets.py +1 -1
  62. meerschaum/api/dash/webterm.py +18 -6
  63. meerschaum/api/models/__init__.py +23 -3
  64. meerschaum/api/models/_actions.py +22 -0
  65. meerschaum/api/models/_pipes.py +91 -7
  66. meerschaum/api/models/_tokens.py +81 -0
  67. meerschaum/api/resources/static/js/terminado.js +3 -0
  68. meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
  69. meerschaum/api/resources/templates/termpage.html +13 -0
  70. meerschaum/api/routes/__init__.py +1 -0
  71. meerschaum/api/routes/_actions.py +3 -4
  72. meerschaum/api/routes/_connectors.py +3 -7
  73. meerschaum/api/routes/_jobs.py +26 -35
  74. meerschaum/api/routes/_login.py +120 -15
  75. meerschaum/api/routes/_misc.py +5 -10
  76. meerschaum/api/routes/_pipes.py +178 -143
  77. meerschaum/api/routes/_plugins.py +38 -28
  78. meerschaum/api/routes/_tokens.py +236 -0
  79. meerschaum/api/routes/_users.py +47 -35
  80. meerschaum/api/routes/_version.py +3 -3
  81. meerschaum/api/routes/_webterm.py +3 -3
  82. meerschaum/config/__init__.py +100 -30
  83. meerschaum/config/_default.py +132 -64
  84. meerschaum/config/_edit.py +38 -32
  85. meerschaum/config/_formatting.py +2 -0
  86. meerschaum/config/_patch.py +10 -8
  87. meerschaum/config/_paths.py +133 -13
  88. meerschaum/config/_read_config.py +87 -36
  89. meerschaum/config/_sync.py +6 -3
  90. meerschaum/config/_version.py +1 -1
  91. meerschaum/config/environment.py +262 -0
  92. meerschaum/config/stack/__init__.py +37 -15
  93. meerschaum/config/static.py +18 -0
  94. meerschaum/connectors/_Connector.py +11 -6
  95. meerschaum/connectors/__init__.py +41 -22
  96. meerschaum/connectors/api/_APIConnector.py +34 -6
  97. meerschaum/connectors/api/_actions.py +2 -2
  98. meerschaum/connectors/api/_jobs.py +12 -1
  99. meerschaum/connectors/api/_login.py +33 -7
  100. meerschaum/connectors/api/_misc.py +2 -2
  101. meerschaum/connectors/api/_pipes.py +23 -32
  102. meerschaum/connectors/api/_plugins.py +2 -2
  103. meerschaum/connectors/api/_request.py +1 -1
  104. meerschaum/connectors/api/_tokens.py +146 -0
  105. meerschaum/connectors/api/_users.py +70 -58
  106. meerschaum/connectors/instance/_InstanceConnector.py +83 -0
  107. meerschaum/connectors/instance/__init__.py +10 -0
  108. meerschaum/connectors/instance/_pipes.py +442 -0
  109. meerschaum/connectors/instance/_plugins.py +159 -0
  110. meerschaum/connectors/instance/_tokens.py +317 -0
  111. meerschaum/connectors/instance/_users.py +188 -0
  112. meerschaum/connectors/parse.py +5 -2
  113. meerschaum/connectors/sql/_SQLConnector.py +22 -5
  114. meerschaum/connectors/sql/_cli.py +12 -11
  115. meerschaum/connectors/sql/_create_engine.py +12 -168
  116. meerschaum/connectors/sql/_fetch.py +2 -18
  117. meerschaum/connectors/sql/_pipes.py +295 -278
  118. meerschaum/connectors/sql/_plugins.py +29 -0
  119. meerschaum/connectors/sql/_sql.py +46 -21
  120. meerschaum/connectors/sql/_users.py +36 -2
  121. meerschaum/connectors/sql/tables/__init__.py +254 -122
  122. meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
  123. meerschaum/connectors/valkey/_pipes.py +60 -31
  124. meerschaum/connectors/valkey/_plugins.py +2 -26
  125. meerschaum/core/Pipe/__init__.py +115 -85
  126. meerschaum/core/Pipe/_attributes.py +425 -124
  127. meerschaum/core/Pipe/_bootstrap.py +54 -24
  128. meerschaum/core/Pipe/_cache.py +555 -0
  129. meerschaum/core/Pipe/_clear.py +0 -11
  130. meerschaum/core/Pipe/_data.py +96 -68
  131. meerschaum/core/Pipe/_deduplicate.py +0 -13
  132. meerschaum/core/Pipe/_delete.py +12 -21
  133. meerschaum/core/Pipe/_drop.py +11 -23
  134. meerschaum/core/Pipe/_dtypes.py +49 -19
  135. meerschaum/core/Pipe/_edit.py +14 -4
  136. meerschaum/core/Pipe/_fetch.py +1 -1
  137. meerschaum/core/Pipe/_index.py +8 -14
  138. meerschaum/core/Pipe/_show.py +5 -5
  139. meerschaum/core/Pipe/_sync.py +123 -204
  140. meerschaum/core/Pipe/_verify.py +4 -4
  141. meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
  142. meerschaum/core/Plugin/__init__.py +1 -1
  143. meerschaum/core/Token/_Token.py +220 -0
  144. meerschaum/core/Token/__init__.py +12 -0
  145. meerschaum/core/User/_User.py +35 -10
  146. meerschaum/core/User/__init__.py +9 -1
  147. meerschaum/core/__init__.py +1 -0
  148. meerschaum/jobs/_Executor.py +88 -4
  149. meerschaum/jobs/_Job.py +149 -38
  150. meerschaum/jobs/__init__.py +3 -2
  151. meerschaum/jobs/systemd.py +8 -3
  152. meerschaum/models/__init__.py +35 -0
  153. meerschaum/models/pipes.py +247 -0
  154. meerschaum/models/tokens.py +38 -0
  155. meerschaum/models/users.py +26 -0
  156. meerschaum/plugins/__init__.py +301 -88
  157. meerschaum/plugins/bootstrap.py +510 -4
  158. meerschaum/utils/_get_pipes.py +97 -30
  159. meerschaum/utils/daemon/Daemon.py +199 -43
  160. meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
  161. meerschaum/utils/daemon/RotatingFile.py +63 -36
  162. meerschaum/utils/daemon/StdinFile.py +53 -13
  163. meerschaum/utils/daemon/__init__.py +47 -6
  164. meerschaum/utils/daemon/_names.py +6 -3
  165. meerschaum/utils/dataframe.py +479 -81
  166. meerschaum/utils/debug.py +49 -19
  167. meerschaum/utils/dtypes/__init__.py +476 -34
  168. meerschaum/utils/dtypes/sql.py +369 -29
  169. meerschaum/utils/formatting/__init__.py +5 -2
  170. meerschaum/utils/formatting/_jobs.py +1 -1
  171. meerschaum/utils/formatting/_pipes.py +52 -50
  172. meerschaum/utils/formatting/_pprint.py +1 -0
  173. meerschaum/utils/formatting/_shell.py +44 -18
  174. meerschaum/utils/misc.py +268 -186
  175. meerschaum/utils/packages/__init__.py +25 -40
  176. meerschaum/utils/packages/_packages.py +42 -34
  177. meerschaum/utils/pipes.py +213 -0
  178. meerschaum/utils/process.py +2 -2
  179. meerschaum/utils/prompt.py +175 -144
  180. meerschaum/utils/schedule.py +2 -1
  181. meerschaum/utils/sql.py +134 -47
  182. meerschaum/utils/threading.py +42 -0
  183. meerschaum/utils/typing.py +1 -4
  184. meerschaum/utils/venv/_Venv.py +2 -2
  185. meerschaum/utils/venv/__init__.py +7 -7
  186. meerschaum/utils/warnings.py +19 -13
  187. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
  188. meerschaum-3.0.0.dist-info/RECORD +289 -0
  189. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
  190. meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
  191. meerschaum/api/models/_interfaces.py +0 -15
  192. meerschaum/api/models/_locations.py +0 -15
  193. meerschaum/api/models/_metrics.py +0 -15
  194. meerschaum/config/_environment.py +0 -145
  195. meerschaum/config/static/__init__.py +0 -186
  196. meerschaum-2.9.5.dist-info/RECORD +0 -263
  197. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
  198. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
  199. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
  200. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
@@ -209,6 +209,8 @@ def get_console():
209
209
  try:
210
210
  console = rich_console.Console(force_terminal=True, color_system='truecolor')
211
211
  except Exception:
212
+ import traceback
213
+ traceback.print_exc()
212
214
  console = None
213
215
  return console
214
216
 
@@ -247,7 +249,7 @@ def print_tuple(
247
249
  If `True`, use the default emoji and color scheme.
248
250
 
249
251
  """
250
- from meerschaum.config.static import STATIC_CONFIG
252
+ from meerschaum._internal.static import STATIC_CONFIG
251
253
  do_print = True
252
254
 
253
255
  omit_messages = STATIC_CONFIG['system']['success']['ignore']
@@ -488,8 +490,9 @@ def fill_ansi(string: str, style: str = '') -> str:
488
490
  msg = Text.from_ansi(string)
489
491
  except AttributeError:
490
492
  import traceback
491
- traceback.print_stack()
493
+ traceback.print_exc()
492
494
  msg = ''
495
+
493
496
  plain_indices = []
494
497
  for left_span, right_span in iterate_chunks(msg.spans, 2, fillvalue=len(msg)):
495
498
  left = left_span.end
@@ -97,7 +97,7 @@ def pprint_jobs(
97
97
  msg = '\n'.join(line.lstrip().rstrip() for line in lines)
98
98
  success_tuple = success, msg
99
99
  success_tuple_str = (
100
- format_success_tuple(success_tuple, left_padding=1)
100
+ format_success_tuple(success_tuple, left_padding=0)
101
101
  if success_tuple is not None
102
102
  else None
103
103
  )
@@ -12,6 +12,7 @@ import meerschaum as mrsm
12
12
  from meerschaum.utils.typing import PipesDict, Dict, Union, Optional, SuccessTuple, Any, List
13
13
  from meerschaum.config import get_config
14
14
 
15
+
15
16
  def pprint_pipes(pipes: PipesDict) -> None:
16
17
  """Print a stylized tree of a Pipes dictionary.
17
18
  Supports ANSI and UNICODE global settings."""
@@ -276,18 +277,31 @@ def pprint_pipe_columns(
276
277
 
277
278
 
278
279
  def pipe_repr(
279
- pipe: mrsm.Pipe,
280
+ pipe: Union[mrsm.Pipe, Dict[str, Any]],
280
281
  as_rich_text: bool = False,
281
282
  ansi: Optional[bool] = None,
282
283
  ) -> Union[str, 'rich.text.Text']:
283
284
  """
284
285
  Return a formatted string for representing a `meerschaum.Pipe`.
285
286
  """
286
- from meerschaum.utils.formatting import UNICODE, ANSI, CHARSET, colored, rich_text_to_str
287
+ from meerschaum.utils.formatting import ANSI, colored, rich_text_to_str
287
288
  from meerschaum.utils.packages import import_rich, attempt_import
288
- rich = import_rich()
289
+ import meerschaum as mrsm
290
+
291
+ _ = import_rich()
289
292
  Text = attempt_import('rich.text').Text
290
293
 
294
+ if isinstance(pipe, mrsm.Pipe):
295
+ connector_keys = pipe.connector_keys
296
+ metric_key = pipe.metric_key
297
+ location_key = pipe.location_key
298
+ instance_keys = pipe.instance_keys
299
+ else:
300
+ connector_keys = pipe.get('connector_keys')
301
+ metric_key = pipe.get('metric_key')
302
+ location_key = pipe.get('location_key')
303
+ instance_keys = pipe.get('instance_keys', get_config('meerschaum', 'instance'))
304
+
291
305
  styles = get_config('formatting', 'pipes', '__repr__', 'ansi', 'styles')
292
306
  if not ANSI or (ansi is False):
293
307
  styles = {k: '' for k in styles}
@@ -297,26 +311,26 @@ def pipe_repr(
297
311
  )
298
312
  text_obj = (
299
313
  Text.from_markup(_pipe_style_prefix + "Pipe(" + _pipe_style_suffix)
300
- + colored(("'" + pipe.connector_keys + "'"), style=styles['connector'], as_rich_text=True)
314
+ + colored(("'" + connector_keys + "'"), style=styles['connector'], as_rich_text=True)
301
315
  + Text.from_markup(_pipe_style_prefix + ", " + _pipe_style_suffix)
302
- + colored(("'" + pipe.metric_key + "'"), style=styles['metric'], as_rich_text=True)
316
+ + colored(("'" + metric_key + "'"), style=styles['metric'], as_rich_text=True)
303
317
  + (
304
318
  (
305
319
  colored(', ', style=styles['punctuation'], as_rich_text=True)
306
320
  + colored(
307
- ("'" + pipe.location_key + "'"),
321
+ ("'" + location_key + "'"),
308
322
  style=styles['location'], as_rich_text=True
309
323
  )
310
- ) if pipe.location_key is not None
324
+ ) if location_key is not None
311
325
  else colored('', style='', as_rich_text=True)
312
326
  ) + (
313
327
  ( ### Add the `instance=` argument.
314
328
  colored(', instance=', style=styles['punctuation'], as_rich_text=True)
315
329
  + colored(
316
- ("'" + pipe.instance_keys + "'"),
330
+ ("'" + instance_keys + "'"),
317
331
  style=styles['instance'], as_rich_text=True
318
332
  )
319
- ) if pipe.instance_keys != get_config('meerschaum', 'instance')
333
+ ) if instance_keys != get_config('meerschaum', 'instance')
320
334
  else colored('', style='', as_rich_text=True)
321
335
  )
322
336
  + Text.from_markup(_pipe_style_prefix + ")" + _pipe_style_suffix)
@@ -326,6 +340,7 @@ def pipe_repr(
326
340
  return rich_text_to_str(text_obj).replace('\n', '')
327
341
 
328
342
 
343
+
329
344
  def highlight_pipes(message: str) -> str:
330
345
  """
331
346
  Add syntax highlighting to an info message containing stringified `meerschaum.Pipe` objects.
@@ -333,56 +348,43 @@ def highlight_pipes(message: str) -> str:
333
348
  if 'Pipe(' not in message:
334
349
  return message
335
350
 
336
- from meerschaum import Pipe
351
+ from meerschaum.utils.misc import parse_arguments_str
337
352
  segments = message.split('Pipe(')
338
353
  msg = ''
339
- _d = {}
340
354
  for i, segment in enumerate(segments):
341
- comma_index = segment.find(',')
342
- paren_index = segment.find(')')
343
- single_quote_index = segment.find("'")
344
- double_quote_index = segment.find('"')
345
-
346
- has_comma = comma_index != -1
347
- has_paren = paren_index != -1
348
- has_single_quote = single_quote_index != -1
349
- has_double_quote = double_quote_index != -1
350
- has_quote = has_single_quote or has_double_quote
351
- quote_index = (
352
- min(single_quote_index, double_quote_index)
353
- if has_double_quote and has_single_quote
354
- else (single_quote_index if has_single_quote else double_quote_index)
355
- )
356
-
357
- has_pipe = (
358
- has_comma
359
- and
360
- has_paren
361
- and
362
- has_quote
363
- and not
364
- (comma_index > paren_index or quote_index > paren_index)
365
- )
355
+ if i == 0:
356
+ msg += segment
357
+ continue
366
358
 
367
- if has_pipe:
368
- code = "_d['pipe'] = Pipe(" + segment[:paren_index + 1]
369
- try:
370
- exec(code)
371
- _to_add = pipe_repr(_d['pipe']) + segment[paren_index + 1:]
372
- _ = _d.pop('pipe', None)
373
- except Exception as e:
374
- _to_add = 'Pipe(' + segment
375
- msg += _to_add
359
+ paren_index = segment.find(')')
360
+ if paren_index == -1:
361
+ msg += 'Pipe(' + segment
376
362
  continue
377
- msg += segment
363
+
364
+ pipe_args_str = segment[:paren_index]
365
+ try:
366
+ args, kwargs = parse_arguments_str(pipe_args_str)
367
+ pipe_dict = {
368
+ 'connector_keys': args[0],
369
+ 'metric_key': args[1],
370
+ }
371
+ if len(args) > 2:
372
+ pipe_dict['location_key'] = args[2]
373
+ if 'instance' in kwargs:
374
+ pipe_dict['instance_keys'] = kwargs['instance']
375
+
376
+ _to_add = pipe_repr(pipe_dict) + segment[paren_index + 1:]
377
+ except Exception:
378
+ _to_add = 'Pipe(' + segment
379
+ msg += _to_add
378
380
  return msg
379
381
 
380
382
 
381
383
  def format_pipe_success_tuple(
382
- pipe: mrsm.Pipe,
383
- success_tuple: SuccessTuple,
384
- nopretty: bool = False,
385
- ) -> str:
384
+ pipe: mrsm.Pipe,
385
+ success_tuple: SuccessTuple,
386
+ nopretty: bool = False,
387
+ ) -> str:
386
388
  """
387
389
  Return a formatted string of a pipe and its resulting SuccessTuple.
388
390
 
@@ -66,6 +66,7 @@ def pprint(
66
66
  except Exception:
67
67
  args_copy = args
68
68
  modify = False
69
+
69
70
  _args = []
70
71
  for a in args:
71
72
  c = a
@@ -6,20 +6,19 @@
6
6
  Formatting functions for the interactive shell
7
7
  """
8
8
 
9
- from re import sub
10
9
  from meerschaum.utils.threading import Lock
11
10
  _locks = {'_tried_clear_command': Lock()}
12
11
 
12
+ from meerschaum._internal.static import STATIC_CONFIG
13
+ FLUSH_TOKEN: str = STATIC_CONFIG['jobs']['flush_token']
13
14
 
14
- def make_header(
15
- message: str,
16
- ruler: str = '─',
17
- ) -> str:
15
+
16
+ def make_header(message: str, ruler: str = '─', left_pad: int = 2) -> str:
18
17
  """Format a message string with a ruler.
19
18
  Length of the ruler is the length of the longest word.
20
19
 
21
20
  Example:
22
- 'My\nheader' -> 'My\nheader\n──────'
21
+ 'My\nheader' -> ' My\n header\n ──────'
23
22
  """
24
23
 
25
24
  from meerschaum.utils.formatting import ANSI, UNICODE, colored
@@ -32,10 +31,15 @@ def make_header(
32
31
  if length > max_length:
33
32
  max_length = length
34
33
 
35
- s = message + "\n"
36
- for i in range(max_length):
37
- s += ruler
38
- return s
34
+ left_buffer = left_pad * ' '
35
+
36
+ return (
37
+ left_buffer
38
+ + message.replace('\n', '\n' + left_buffer)
39
+ + "\n"
40
+ + left_buffer
41
+ + (ruler * max_length)
42
+ )
39
43
 
40
44
 
41
45
  _tried_clear_command = None
@@ -49,28 +53,40 @@ def clear_screen(debug: bool = False) -> bool:
49
53
  from meerschaum.utils.debug import dprint
50
54
  from meerschaum.config import get_config
51
55
  from meerschaum.utils.daemon import running_in_daemon
56
+ from meerschaum._internal.static import STATIC_CONFIG
52
57
  global _tried_clear_command
58
+ clear_string = '\033[2J'
59
+ reset_string = '\033[0m'
60
+ clear_token = STATIC_CONFIG['jobs']['clear_token']
53
61
 
54
- if running_in_daemon():
62
+ if not get_config('shell', 'clear_screen'):
55
63
  return True
56
64
 
57
- if not get_config('shell', 'clear_screen'):
65
+ if running_in_daemon():
66
+ if debug:
67
+ dprint("Skip printing clear token.")
68
+ flush_stdout()
69
+ return True
70
+
71
+ print(clear_token, flush=True)
58
72
  return True
59
73
 
60
- print("", end="", flush=True)
74
+
75
+ flush_stdout()
61
76
  if debug:
62
77
  dprint("Skipping screen clear.")
63
78
  return True
79
+
64
80
  if ANSI and platform.system() != 'Windows':
65
81
  if get_console() is not None:
66
82
  get_console().clear()
67
- print("", end="", flush=True)
83
+ flush_stdout()
68
84
  return True
69
- clear_string = '\033[2J'
70
- reset_string = '\033[0m'
85
+
71
86
  print(clear_string + reset_string, end="")
72
- print("", end="", flush=True)
87
+ flush_stdout()
73
88
  return True
89
+
74
90
  ### ANSI support is disabled, try system level instead
75
91
  if _tried_clear_command is not None:
76
92
  return os.system(_tried_clear_command) == 0
@@ -79,7 +95,7 @@ def clear_screen(debug: bool = False) -> bool:
79
95
  command = 'clear' if platform.system() != 'Windows' else 'cls'
80
96
  try:
81
97
  rc = os.system(command)
82
- except Exception as e:
98
+ except Exception:
83
99
  pass
84
100
  if rc == 0:
85
101
  with _locks['_tried_clear_command']:
@@ -87,6 +103,16 @@ def clear_screen(debug: bool = False) -> bool:
87
103
  return rc == 0
88
104
 
89
105
 
106
+ def flush_stdout():
107
+ """
108
+ Flush stdout, including printing the flush token for daemons.
109
+ """
110
+ from meerschaum.utils.daemon import running_in_daemon
111
+ print('', end='', flush=True)
112
+ if running_in_daemon():
113
+ print(FLUSH_TOKEN, end='', flush=True)
114
+
115
+
90
116
  def flush_with_newlines(debug: bool = False) -> None:
91
117
  """Print newlines such that the entire terminal is cleared and new text will show up at the bottom."""
92
118
  import sys