meerschaum 2.7.5__py3-none-any.whl → 2.7.6__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 (30) hide show
  1. meerschaum/_internal/shell/Shell.py +4 -6
  2. meerschaum/_internal/shell/ShellCompleter.py +6 -5
  3. meerschaum/actions/clear.py +6 -3
  4. meerschaum/actions/copy.py +33 -27
  5. meerschaum/actions/sync.py +22 -18
  6. meerschaum/api/dash/pipes.py +2 -3
  7. meerschaum/config/_default.py +5 -0
  8. meerschaum/config/_version.py +1 -1
  9. meerschaum/connectors/api/_misc.py +3 -2
  10. meerschaum/connectors/api/_pipes.py +8 -9
  11. meerschaum/connectors/sql/_SQLConnector.py +1 -0
  12. meerschaum/connectors/sql/_pipes.py +37 -10
  13. meerschaum/connectors/sql/_sql.py +9 -1
  14. meerschaum/jobs/_Job.py +1 -0
  15. meerschaum/plugins/__init__.py +7 -3
  16. meerschaum/utils/daemon/Daemon.py +5 -1
  17. meerschaum/utils/daemon/__init__.py +2 -2
  18. meerschaum/utils/misc.py +7 -6
  19. meerschaum/utils/packages/__init__.py +31 -27
  20. meerschaum/utils/packages/_packages.py +1 -1
  21. meerschaum/utils/prompt.py +54 -36
  22. meerschaum/utils/venv/__init__.py +12 -3
  23. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/METADATA +4 -4
  24. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/RECORD +30 -30
  25. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/WHEEL +1 -1
  26. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/LICENSE +0 -0
  27. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/NOTICE +0 -0
  28. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/entry_points.txt +0 -0
  29. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/top_level.txt +0 -0
  30. {meerschaum-2.7.5.dist-info → meerschaum-2.7.6.dist-info}/zip-safe +0 -0
@@ -742,8 +742,7 @@ class Shell(cmd.Cmd):
742
742
  """
743
743
  from meerschaum import get_connector
744
744
  from meerschaum.connectors.parse import parse_instance_keys
745
- from meerschaum.utils.warnings import warn, info
746
- from meerschaum.utils.misc import remove_ansi
745
+ from meerschaum.utils.warnings import info
747
746
 
748
747
  if action is None:
749
748
  action = []
@@ -829,7 +828,7 @@ class Shell(cmd.Cmd):
829
828
  """
830
829
  from meerschaum import get_connector
831
830
  from meerschaum.connectors.parse import parse_repo_keys
832
- from meerschaum.utils.warnings import warn, info
831
+ from meerschaum.utils.warnings import info
833
832
 
834
833
  if action is None:
835
834
  action = []
@@ -878,7 +877,6 @@ class Shell(cmd.Cmd):
878
877
 
879
878
  Note that executors are API instances.
880
879
  """
881
- from meerschaum import get_connector
882
880
  from meerschaum.connectors.parse import parse_executor_keys
883
881
  from meerschaum.utils.warnings import warn, info
884
882
  from meerschaum.jobs import get_executor_keys_from_context
@@ -894,7 +892,7 @@ class Shell(cmd.Cmd):
894
892
  executor_keys = get_executor_keys_from_context()
895
893
 
896
894
  if executor_keys == 'systemd' and get_executor_keys_from_context() != 'systemd':
897
- warn(f"Cannot execute via `systemd`, falling back to `local`...", stack=False)
895
+ warn("Cannot execute via `systemd`, falling back to `local`...", stack=False)
898
896
  executor_keys = 'local'
899
897
 
900
898
  conn = parse_executor_keys(executor_keys, debug=debug)
@@ -935,7 +933,7 @@ class Shell(cmd.Cmd):
935
933
  if args['action'][0] not in shell_attrs['_actions']:
936
934
  try:
937
935
  print(textwrap.dedent(getattr(self, f"do_{args['action'][0]}").__doc__))
938
- except Exception as e:
936
+ except Exception:
939
937
  print(f"No help on '{args['action'][0]}'.")
940
938
  return ""
941
939
  parse_help(args)
@@ -7,13 +7,15 @@ Implement the prompt_toolkit Completer base class.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
- from prompt_toolkit.completion import Completer, Completion
11
- from meerschaum.utils.typing import Optional
12
- from meerschaum.actions import get_shell, get_completer, get_main_action_name, get_action
10
+ from meerschaum.actions import get_shell, get_main_action_name, get_action
13
11
  from meerschaum._internal.arguments import parse_line
14
12
 
15
13
  from meerschaum.utils.packages import attempt_import, ensure_readline
16
- prompt_toolkit = attempt_import('prompt_toolkit', lazy=False, install=True)
14
+
15
+ prompt_toolkit_completion = attempt_import('prompt_toolkit.completion', lazy=False, install=True)
16
+ Completer = prompt_toolkit_completion.Completer
17
+ Completion = prompt_toolkit_completion.Completion
18
+
17
19
 
18
20
  class ShellCompleter(Completer):
19
21
  """
@@ -30,7 +32,6 @@ class ShellCompleter(Completer):
30
32
  yielded = []
31
33
  ensure_readline()
32
34
  parts = document.text.split('-')
33
- ends_with_space = parts[0].endswith(' ')
34
35
  last_action_line = parts[0].split('+')[-1]
35
36
  part_0_subbed_spaces = last_action_line.replace(' ', '_')
36
37
  parsed_text = (part_0_subbed_spaces + '-'.join(parts[1:]))
@@ -130,12 +130,15 @@ def _ask_with_rowcounts(
130
130
  )
131
131
 
132
132
 
133
- pipes_rowcounts = {p: p.get_rowcount(begin=begin, end=end, debug=debug) for p in pipes}
133
+ pipes_rowcounts = {
134
+ pipe: pipe.get_rowcount(begin=begin, end=end, debug=debug)
135
+ for pipe in pipes
136
+ }
134
137
  print_options(
135
- [str(p) + f'\n{rc}\n' for p, rc in pipes_rowcounts.items()],
138
+ [str(pipe) + f'\n{rowcount:,}\n' for pipe, rowcount in pipes_rowcounts.items()],
136
139
  header='Number of Rows to be Deleted'
137
140
  )
138
- total_num_rows = sum([rc for p, rc in pipes_rowcounts.items()])
141
+ total_num_rows = sum([rowcount for rowcount in pipes_rowcounts.values()])
139
142
  question = (
140
143
  f"Are you sure you want to delete {total_num_rows:,} rows across {len(pipes)} pipe"
141
144
  + ('s' if len(pipes) != 1 else '')
@@ -7,7 +7,7 @@ Functions for copying elements.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
- from meerschaum.utils.typing import Union, Any, Sequence, SuccessTuple, Optional, Tuple, List
10
+ from meerschaum.utils.typing import Any, SuccessTuple, Optional, List
11
11
 
12
12
  def copy(
13
13
  action: Optional[List[str]] = None,
@@ -69,44 +69,53 @@ def _copy_pipes(
69
69
  Copy pipes' attributes and make new pipes.
70
70
  """
71
71
  from meerschaum import get_pipes, Pipe
72
- from meerschaum.utils.prompt import prompt, yes_no
72
+ from meerschaum.utils.prompt import prompt, yes_no, get_connectors_completer
73
73
  from meerschaum.utils.warnings import warn
74
74
  from meerschaum.utils.formatting import print_tuple
75
75
  from meerschaum.utils.formatting._shell import clear_screen
76
76
  pipes = get_pipes(as_list=True, **kw)
77
77
  successes = 0
78
- for p in pipes:
79
- ck = prompt(f"Connector keys for copy of {p}:", default=p.connector_keys)
80
- mk = prompt(f"Metric key for copy of {p}:", default=p.metric_key)
81
- lk = prompt(f"Location key for copy of {p} ('None' to omit):", default=str(p.location_key))
78
+ for pipe in pipes:
79
+ ck = prompt(
80
+ f"Connector keys for copy of {pipe}:",
81
+ default=pipe.connector_keys,
82
+ completer=get_connectors_completer(),
83
+ )
84
+ mk = prompt(f"Metric key for copy of {pipe}:", default=pipe.metric_key)
85
+ lk = prompt(
86
+ f"Location key for copy of {pipe} ('None' to omit):",
87
+ default=str(pipe.location_key),
88
+ )
82
89
  if lk in ('', 'None', '[None]'):
83
90
  lk = None
84
- _new_pipe = Pipe(
85
- ck, mk, lk,
86
- parameters=p.parameters.copy(),
87
- )
91
+
88
92
  instance_keys = prompt(
89
- f"Meerschaum instance to store the new {_new_pipe}:",
90
- default=p.instance_keys
93
+ f"Meerschaum instance for copy of {pipe}:",
94
+ default=pipe.instance_keys
91
95
  )
92
- _new_pipe.instance_keys = instance_keys
93
- if _new_pipe.get_id(debug=debug) is not None:
94
- warn(f"New {_new_pipe} already exists. Skipping...", stack=False)
96
+ new_pipe = Pipe(
97
+ ck, mk, lk,
98
+ instance=instance_keys,
99
+ parameters=pipe.parameters.copy(),
100
+ )
101
+
102
+ if new_pipe.get_id(debug=debug) is not None:
103
+ warn(f"{new_pipe} already exists. Skipping...", stack=False)
95
104
  continue
96
- _register_success_tuple = _new_pipe.register(debug=debug)
105
+ _register_success_tuple = new_pipe.register(debug=debug)
97
106
  if not _register_success_tuple[0]:
98
- warn(f"Failed to register new {_new_pipe}.", stack=False)
107
+ warn(f"Failed to register new {new_pipe}.", stack=False)
99
108
  continue
100
109
 
101
110
  clear_screen(debug=debug)
102
111
  successes += 1
103
112
  print_tuple(
104
- (True, f"Successfully copied attributes of {p} " + f" into {_new_pipe}.")
113
+ (True, f"Successfully copied attributes of {pipe} " + f" into {new_pipe}.")
105
114
  )
106
115
  if (
107
116
  force or yes_no(
108
117
  (
109
- f"Do you want to copy data from {p} into {_new_pipe}?\n\n"
118
+ f"Do you want to copy data from {pipe} into {new_pipe}?\n\n"
110
119
  + "If you specified `--begin`, `--end` or `--params`, data will be filtered."
111
120
  ),
112
121
  noask=noask,
@@ -114,8 +123,8 @@ def _copy_pipes(
114
123
  default='n',
115
124
  )
116
125
  ):
117
- _new_pipe.sync(
118
- p.get_data(
126
+ new_pipe.sync(
127
+ pipe.get_data(
119
128
  debug=debug,
120
129
  as_iterator=True,
121
130
  **kw
@@ -142,17 +151,14 @@ def _copy_connectors(
142
151
  ) -> SuccessTuple:
143
152
  """
144
153
  Create a new connector from an existing one.
145
-
146
154
  """
147
- import os, pathlib
148
155
  from meerschaum.utils.prompt import yes_no, prompt
149
156
  from meerschaum.connectors.parse import parse_connector_keys
150
157
  from meerschaum.config import _config, get_config
151
- from meerschaum.config._edit import write_config
152
- from meerschaum.utils.warnings import info, warn
158
+ from meerschaum.utils.warnings import info
153
159
  from meerschaum.utils.formatting import pprint
154
160
  from meerschaum.actions import get_action
155
- cf = _config()
161
+ _ = _config()
156
162
  if action is None:
157
163
  action = []
158
164
  if connector_keys is None:
@@ -170,7 +176,7 @@ def _copy_connectors(
170
176
 
171
177
  try:
172
178
  conn = parse_connector_keys(ck)
173
- except Exception as e:
179
+ except Exception:
174
180
  return False, f"Unable to parse connector '{ck}'."
175
181
 
176
182
  if len(_keys) == 2:
@@ -275,12 +275,14 @@ def _sync_pipes(
275
275
  import time
276
276
  import os
277
277
  import contextlib
278
+ from datetime import timedelta
278
279
 
279
280
  from meerschaum.utils.warnings import warn, info
280
281
  from meerschaum.utils.formatting._shell import progress
281
282
  from meerschaum.utils.formatting._shell import clear_screen
282
283
  from meerschaum.utils.formatting import print_pipes_results
283
284
  from meerschaum.config.static import STATIC_CONFIG
285
+ from meerschaum.utils.misc import interval_str
284
286
 
285
287
  noninteractive_val = os.environ.get(STATIC_CONFIG['environment']['noninteractive'], None)
286
288
  noninteractive = str(noninteractive_val).lower() in ('1', 'true', 'yes')
@@ -321,7 +323,7 @@ def _sync_pipes(
321
323
  for pipe, (_success, _msg) in results_dict.items()
322
324
  if not _success
323
325
  ]
324
- except Exception as e:
326
+ except Exception:
325
327
  import traceback
326
328
  traceback.print_exc()
327
329
  warn(
@@ -351,9 +353,9 @@ def _sync_pipes(
351
353
  success_msg = (
352
354
  "Successfully spawned threads for pipes:"
353
355
  if unblock
354
- else f"Successfully synced pipes:"
356
+ else "Successfully synced pipes:"
355
357
  )
356
- fail_msg = f"Failed to sync pipes:"
358
+ fail_msg = "Failed to sync pipes:"
357
359
  if results_dict:
358
360
  print_pipes_results(
359
361
  results_dict,
@@ -362,8 +364,10 @@ def _sync_pipes(
362
364
  nopretty = nopretty,
363
365
  )
364
366
 
367
+ lap_duration_text = interval_str(timedelta(seconds=(lap_end - lap_begin)))
368
+
365
369
  msg = (
366
- f"It took {round(lap_end - lap_begin, 2)} seconds to sync " +
370
+ f"It took {lap_duration_text} to sync " +
367
371
  f"{len(success_pipes) + len(failure_pipes)} pipe" +
368
372
  ("s" if (len(success_pipes) + len(failure_pipes)) != 1 else "") + "\n" +
369
373
  f" ({len(success_pipes)} succeeded, {len(failure_pipes)} failed)."
@@ -385,26 +389,26 @@ def _sync_pipes(
385
389
 
386
390
 
387
391
  def _wrap_pipe(
388
- pipe,
389
- unblock: bool = False,
390
- force: bool = False,
391
- debug: bool = False,
392
- min_seconds: int = 1,
393
- workers = None,
394
- verify: bool = False,
395
- deduplicate: bool = False,
396
- bounded: Optional[bool] = None,
397
- chunk_interval: Union[timedelta, int, None] = None,
398
- **kw
399
- ):
392
+ pipe,
393
+ unblock: bool = False,
394
+ force: bool = False,
395
+ debug: bool = False,
396
+ min_seconds: int = 1,
397
+ workers = None,
398
+ verify: bool = False,
399
+ deduplicate: bool = False,
400
+ bounded: Optional[bool] = None,
401
+ chunk_interval: Union[timedelta, int, None] = None,
402
+ **kw
403
+ ):
400
404
  """
401
405
  Wrapper function for handling exceptions.
402
406
  """
403
407
  import time
404
408
  import traceback
405
- from datetime import datetime, timedelta, timezone
409
+ from datetime import datetime, timezone
406
410
  import meerschaum as mrsm
407
- from meerschaum.utils.typing import is_success_tuple, SuccessTuple
411
+ from meerschaum.utils.typing import is_success_tuple
408
412
  from meerschaum.connectors import get_connector_plugin
409
413
  from meerschaum.utils.venv import Venv
410
414
  from meerschaum.plugins import _pre_sync_hooks, _post_sync_hooks
@@ -12,7 +12,6 @@ import shlex
12
12
  from textwrap import dedent
13
13
  from urllib.parse import urlencode
14
14
 
15
- from dash.dependencies import Input, Output, State
16
15
  from meerschaum.utils.typing import List, Optional, Dict, Any, Tuple, Union
17
16
  from meerschaum.utils.misc import string_to_dict
18
17
  from meerschaum.utils.packages import attempt_import, import_dcc, import_html, import_pandas
@@ -76,7 +75,7 @@ def keys_from_state(
76
75
  try:
77
76
  # params = string_to_dict(state['params-textarea.value'])
78
77
  params = string_to_dict(state['search-parameters-editor.value'])
79
- except Exception as e:
78
+ except Exception:
80
79
  params = None
81
80
  else:
82
81
  params = None
@@ -506,7 +505,7 @@ def accordion_items_from_pipe(
506
505
 
507
506
  stats_rows = []
508
507
  if rowcount is not None:
509
- stats_rows.append(html.Tr([html.Td("Row-count"), html.Td(f"{rowcount}")]))
508
+ stats_rows.append(html.Tr([html.Td("Row Count"), html.Td(f"{rowcount:,}")]))
510
509
  if interval is not None:
511
510
  stats_rows.append(
512
511
  html.Tr([html.Td("Timespan"), html.Td(humanfriendly.format_timespan(interval))])
@@ -76,6 +76,11 @@ default_system_config = {
76
76
  },
77
77
  'instance': {
78
78
  'stale_temporary_tables_minutes': 1440,
79
+ 'temporary_target': {
80
+ 'prefix': '_',
81
+ 'transaction_id_length': 4,
82
+ 'separator': '_',
83
+ },
79
84
  },
80
85
  'chunksize': 100_000,
81
86
  'poolclass': 'sqlalchemy.pool.QueuePool',
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "2.7.5"
5
+ __version__ = "2.7.6"
@@ -20,12 +20,13 @@ def get_mrsm_version(self, **kw) -> Optional[str]:
20
20
  use_token=False,
21
21
  **kw
22
22
  ).json()
23
- except Exception as e:
23
+ except Exception:
24
24
  return None
25
25
  if isinstance(j, dict) and 'detail' in j:
26
26
  return None
27
27
  return j
28
28
 
29
+
29
30
  def get_chaining_status(self, **kw) -> Optional[bool]:
30
31
  """
31
32
  Fetch the chaining status of the API instance.
@@ -39,7 +40,7 @@ def get_chaining_status(self, **kw) -> Optional[bool]:
39
40
  )
40
41
  if not response:
41
42
  return None
42
- except Exception as e:
43
+ except Exception:
43
44
  return None
44
45
 
45
46
  return response.json()
@@ -9,8 +9,7 @@ Register or fetch Pipes from the API
9
9
  from __future__ import annotations
10
10
  import time
11
11
  import json
12
- from io import StringIO
13
- from datetime import datetime
12
+ from datetime import datetime, timedelta
14
13
 
15
14
  import meerschaum as mrsm
16
15
  from meerschaum.utils.debug import dprint
@@ -178,11 +177,11 @@ def sync_pipe(
178
177
  """Sync a DataFrame into a Pipe."""
179
178
  from decimal import Decimal
180
179
  from meerschaum.utils.debug import dprint
181
- from meerschaum.utils.misc import json_serialize_datetime, items_str
180
+ from meerschaum.utils.misc import json_serialize_datetime, items_str, interval_str
182
181
  from meerschaum.config import get_config
183
182
  from meerschaum.utils.packages import attempt_import
184
- from meerschaum.utils.dataframe import get_numeric_cols, to_json, get_bytes_cols
185
- begin = time.time()
183
+ from meerschaum.utils.dataframe import get_numeric_cols, to_json
184
+ begin = time.perf_counter()
186
185
  more_itertools = attempt_import('more_itertools')
187
186
  if df is None:
188
187
  msg = f"DataFrame is `None`. Cannot sync {pipe}."
@@ -304,9 +303,10 @@ def sync_pipe(
304
303
  num_success_chunks += 1
305
304
 
306
305
  success_tuple = True, (
307
- f"It took {round(time.time() - begin, 2)} seconds to sync {rowcount} row"
306
+ f"It took {interval_str(timedelta(seconds=(time.perf_counter() - begin)))} "
307
+ + "to sync {rowcount:,} row"
308
308
  + ('s' if rowcount != 1 else '')
309
- + f" across {num_success_chunks} chunk" + ('s' if num_success_chunks != 1 else '') +
309
+ + f" across {num_success_chunks:,} chunk" + ('s' if num_success_chunks != 1 else '') +
310
310
  f" to {pipe}."
311
311
  )
312
312
  return success_tuple
@@ -549,10 +549,9 @@ def create_metadata(
549
549
  if debug:
550
550
  dprint("Create metadata response: {response.text}")
551
551
  try:
552
- metadata_response = json.loads(response.text)
552
+ _ = json.loads(response.text)
553
553
  except Exception as e:
554
554
  warn(f"Failed to create metadata on {self}:\n{e}")
555
- metadata_response = False
556
555
  return False
557
556
 
558
557
 
@@ -69,6 +69,7 @@ class SQLConnector(Connector):
69
69
  get_pipe_schema,
70
70
  create_pipe_table_from_df,
71
71
  get_pipe_columns_indices,
72
+ get_temporary_target,
72
73
  )
73
74
  from ._plugins import (
74
75
  register_plugin,
@@ -1505,7 +1505,6 @@ def sync_pipe(
1505
1505
  UPDATE_QUERIES,
1506
1506
  get_reset_autoincrement_queries,
1507
1507
  )
1508
- from meerschaum.utils.misc import generate_password
1509
1508
  from meerschaum.utils.dtypes import are_dtypes_equal
1510
1509
  from meerschaum.utils.dtypes.sql import get_db_type_from_pd_type
1511
1510
  from meerschaum import Pipe
@@ -1720,9 +1719,7 @@ def sync_pipe(
1720
1719
  warn(f"Could not reset auto-incrementing primary key for {pipe}.", stack=False)
1721
1720
 
1722
1721
  if update_df is not None and len(update_df) > 0:
1723
- transact_id = generate_password(3)
1724
- temp_prefix = '##' if self.flavor != 'oracle' else '_'
1725
- temp_target = temp_prefix + transact_id + '_' + pipe.target
1722
+ temp_target = self.get_temporary_target(pipe.target, label='update')
1726
1723
  self._log_temporary_tables_creation(temp_target, create=(not pipe.temporary), debug=debug)
1727
1724
  temp_pipe = Pipe(
1728
1725
  pipe.connector_keys.replace(':', '_') + '_', pipe.metric_key, pipe.location_key,
@@ -1743,7 +1740,7 @@ def sync_pipe(
1743
1740
  static=True,
1744
1741
  autoincrement=False,
1745
1742
  parameters={
1746
- 'schema': (self.internal_schema if self.flavor != 'mssql' else None),
1743
+ 'schema': self.internal_schema,
1747
1744
  'hypertable': False,
1748
1745
  },
1749
1746
  )
@@ -1910,15 +1907,18 @@ def sync_pipe_inplace(
1910
1907
  )
1911
1908
  from meerschaum.utils.misc import generate_password
1912
1909
 
1913
- transact_id = generate_password(3)
1914
- def get_temp_table_name(label: str) -> str:
1915
- temp_prefix = '##' if self.flavor != 'oracle' else '_'
1916
- return temp_prefix + transact_id + '_' + label + '_' + pipe.target
1910
+ transaction_id_length = (
1911
+ mrsm.get_config(
1912
+ 'system', 'connectors', 'sql', 'instance', 'temporary_target', 'transaction_id_length'
1913
+ )
1914
+ )
1915
+ transact_id = generate_password(transaction_id_length)
1917
1916
 
1918
1917
  internal_schema = self.internal_schema
1918
+ target = pipe.target
1919
1919
  temp_table_roots = ['backtrack', 'new', 'delta', 'joined', 'unseen', 'update']
1920
1920
  temp_tables = {
1921
- table_root: get_temp_table_name(table_root)
1921
+ table_root: self.get_temporary_target(target, transact_id=transact_id, label=table_root)
1922
1922
  for table_root in temp_table_roots
1923
1923
  }
1924
1924
  temp_table_names = {
@@ -3626,3 +3626,30 @@ def get_pipe_schema(self, pipe: mrsm.Pipe) -> Union[str, None]:
3626
3626
  A schema string or `None` if nothing is configured.
3627
3627
  """
3628
3628
  return pipe.parameters.get('schema', self.schema)
3629
+
3630
+
3631
+ @staticmethod
3632
+ def get_temporary_target(
3633
+ target: str,
3634
+ transact_id: Optional[str, None] = None,
3635
+ label: Optional[str] = None,
3636
+ separator: Optional[str] = None,
3637
+ ) -> str:
3638
+ """
3639
+ Return a unique(ish) temporary target for a pipe.
3640
+ """
3641
+ from meerschaum.utils.misc import generate_password
3642
+ temp_target_cf = (
3643
+ mrsm.get_config('system', 'connectors', 'sql', 'instance', 'temporary_target') or {}
3644
+ )
3645
+ transaction_id_len = temp_target_cf.get('transaction_id_length', 3)
3646
+ transact_id = transact_id or generate_password(transaction_id_len)
3647
+ temp_prefix = temp_target_cf.get('prefix', '_')
3648
+ separator = separator or temp_target_cf.get('separator', '_')
3649
+ return (
3650
+ temp_prefix
3651
+ + target
3652
+ + separator
3653
+ + transact_id
3654
+ + ((separator + label) if label else '')
3655
+ )
@@ -778,6 +778,7 @@ def to_sql(
778
778
  import time
779
779
  import json
780
780
  from decimal import Decimal
781
+ from datetime import timedelta
781
782
  from meerschaum.utils.warnings import error, warn
782
783
  import warnings
783
784
  import functools
@@ -816,6 +817,7 @@ def to_sql(
816
817
  PD_TO_SQLALCHEMY_DTYPES_FLAVORS,
817
818
  get_db_type_from_pd_type,
818
819
  )
820
+ from meerschaum.utils.misc import interval_str
819
821
  from meerschaum.connectors.sql._create_engine import flavor_configs
820
822
  from meerschaum.utils.packages import attempt_import, import_pandas
821
823
  sqlalchemy = attempt_import('sqlalchemy', debug=debug)
@@ -998,7 +1000,13 @@ def to_sql(
998
1000
 
999
1001
  end = time.perf_counter()
1000
1002
  if success:
1001
- msg = f"It took {round(end - start, 2)} seconds to sync {len(df)} rows to {name}."
1003
+ num_rows = len(df)
1004
+ msg = (
1005
+ f"It took {interval_str(timedelta(seconds=(end - start)))} "
1006
+ + f"to sync {num_rows:,} row"
1007
+ + ('s' if num_rows != 1 else '')
1008
+ + f" to {name}."
1009
+ )
1002
1010
  stats['start'] = start
1003
1011
  stats['end'] = end
1004
1012
  stats['duration'] = end - start
meerschaum/jobs/_Job.py CHANGED
@@ -313,6 +313,7 @@ class Job:
313
313
  if not cleanup_success:
314
314
  return cleanup_success, cleanup_msg
315
315
 
316
+ _ = self.daemon._properties.pop('result', None)
316
317
  return cleanup_success, f"Deleted {self}."
317
318
 
318
319
  def is_running(self) -> bool:
@@ -126,8 +126,8 @@ def pre_sync_hook(
126
126
 
127
127
 
128
128
  def post_sync_hook(
129
- function: Callable[[Any], Any],
130
- ) -> Callable[[Any], Any]:
129
+ function: Callable[[Any], Any],
130
+ ) -> Callable[[Any], Any]:
131
131
  """
132
132
  Register a function as a sync hook to be executed upon completion of a sync.
133
133
 
@@ -143,10 +143,14 @@ def post_sync_hook(
143
143
  Examples
144
144
  --------
145
145
  >>> from meerschaum.plugins import post_sync_hook
146
+ >>> from meerschaum.utils.misc import interval_str
147
+ >>> from datetime import timedelta
146
148
  >>>
147
149
  >>> @post_sync_hook
148
150
  ... def log_sync(pipe, success_tuple, duration=None, **kwargs):
149
- ... print(f"It took {round(duration, 2)} seconds to sync {pipe}.")
151
+ ... duration_delta = timedelta(seconds=duration)
152
+ ... duration_text = interval_str(duration_delta)
153
+ ... print(f"It took {duration_text} to sync {pipe}.")
150
154
  >>>
151
155
  """
152
156
  with _locks['_post_sync_hooks']:
@@ -1017,7 +1017,8 @@ class Daemon:
1017
1017
 
1018
1018
  def read_pickle(self) -> Daemon:
1019
1019
  """Read a Daemon's pickle file and return the `Daemon`."""
1020
- import pickle, traceback
1020
+ import pickle
1021
+ import traceback
1021
1022
  if not self.pickle_path.exists():
1022
1023
  error(f"Pickle file does not exist for daemon '{self.daemon_id}'.")
1023
1024
 
@@ -1053,6 +1054,9 @@ class Daemon:
1053
1054
  if self._properties is None:
1054
1055
  self._properties = {}
1055
1056
 
1057
+ if self._properties.get('result', None) is None:
1058
+ _ = self._properties.pop('result', None)
1059
+
1056
1060
  if _file_properties is not None:
1057
1061
  self._properties = apply_patch_to_config(
1058
1062
  _file_properties,
@@ -37,7 +37,7 @@ def daemon_entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
37
37
  filtered_sysargs = [arg for arg in sysargs if arg not in ('-d', '--daemon')]
38
38
  try:
39
39
  label = shlex.join(filtered_sysargs) if sysargs else None
40
- except Exception as e:
40
+ except Exception:
41
41
  label = ' '.join(filtered_sysargs) if sysargs else None
42
42
 
43
43
  name = _args.get('name', None)
@@ -45,7 +45,7 @@ def daemon_entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
45
45
  if name:
46
46
  try:
47
47
  daemon = Daemon(daemon_id=name)
48
- except Exception as e:
48
+ except Exception:
49
49
  daemon = None
50
50
 
51
51
  if daemon is not None:
meerschaum/utils/misc.py CHANGED
@@ -90,20 +90,21 @@ def add_method_to_class(
90
90
 
91
91
 
92
92
  def generate_password(length: int = 12) -> str:
93
- """Generate a secure password of given length.
93
+ """
94
+ Generate a secure password of given length.
94
95
 
95
96
  Parameters
96
97
  ----------
97
- length : int, default 12
98
+ length: int, default 12
98
99
  The length of the password.
99
100
 
100
101
  Returns
101
102
  -------
102
103
  A random password string.
103
-
104
104
  """
105
- import secrets, string
106
- return ''.join((secrets.choice(string.ascii_letters) for i in range(length)))
105
+ import secrets
106
+ import string
107
+ return ''.join((secrets.choice(string.ascii_letters + string.digits) for i in range(length)))
107
108
 
108
109
  def is_int(s : str) -> bool:
109
110
  """
@@ -121,7 +122,7 @@ def is_int(s : str) -> bool:
121
122
  """
122
123
  try:
123
124
  float(s)
124
- except Exception as e:
125
+ except Exception:
125
126
  return False
126
127
 
127
128
  return float(s).is_integer()
@@ -337,14 +337,14 @@ def get_install_no_version(install_name: str) -> str:
337
337
 
338
338
  import_versions = {}
339
339
  def determine_version(
340
- path: pathlib.Path,
341
- import_name: Optional[str] = None,
342
- venv: Optional[str] = 'mrsm',
343
- search_for_metadata: bool = True,
344
- split: bool = True,
345
- warn: bool = False,
346
- debug: bool = False,
347
- ) -> Union[str, None]:
340
+ path: pathlib.Path,
341
+ import_name: Optional[str] = None,
342
+ venv: Optional[str] = 'mrsm',
343
+ search_for_metadata: bool = True,
344
+ split: bool = True,
345
+ warn: bool = False,
346
+ debug: bool = False,
347
+ ) -> Union[str, None]:
348
348
  """
349
349
  Determine a module's `__version__` string from its filepath.
350
350
 
@@ -381,11 +381,8 @@ def determine_version(
381
381
  with _locks['import_versions']:
382
382
  if venv not in import_versions:
383
383
  import_versions[venv] = {}
384
- import importlib.metadata
385
- import re, os
384
+ import os
386
385
  old_cwd = os.getcwd()
387
- if debug:
388
- from meerschaum.utils.debug import dprint
389
386
  from meerschaum.utils.warnings import warn as warn_function
390
387
  if import_name is None:
391
388
  import_name = path.parent.stem if path.stem == '__init__' else path.stem
@@ -395,7 +392,10 @@ def determine_version(
395
392
  _version = None
396
393
  module_parent_dir = (
397
394
  path.parent.parent if path.stem == '__init__' else path.parent
398
- ) if path is not None else venv_target_path(venv, debug=debug)
395
+ ) if path is not None else venv_target_path(venv, allow_nonexistent=True, debug=debug)
396
+
397
+ if not module_parent_dir.exists():
398
+ return None
399
399
 
400
400
  installed_dir_name = _import_to_dir_name(import_name)
401
401
  clean_installed_dir_name = installed_dir_name.lower().replace('-', '_')
@@ -403,7 +403,11 @@ def determine_version(
403
403
  ### First, check if a dist-info directory exists.
404
404
  _found_versions = []
405
405
  if search_for_metadata:
406
- for filename in os.listdir(module_parent_dir):
406
+ try:
407
+ filenames = os.listdir(module_parent_dir)
408
+ except FileNotFoundError:
409
+ filenames = []
410
+ for filename in filenames:
407
411
  if not filename.endswith('.dist-info'):
408
412
  continue
409
413
  filename_lower = filename.lower()
@@ -430,7 +434,7 @@ def determine_version(
430
434
  try:
431
435
  os.chdir(module_parent_dir)
432
436
  _version = importlib_metadata.metadata(import_name)['Version']
433
- except Exception as e:
437
+ except Exception:
434
438
  _version = None
435
439
  finally:
436
440
  os.chdir(old_cwd)
@@ -698,7 +702,7 @@ def need_update(
698
702
  (not semver.Version.parse(version).match(required_version))
699
703
  if required_version else False
700
704
  )
701
- except AttributeError as e:
705
+ except AttributeError:
702
706
  pip_install(_import_to_install_name('semver'), venv='mrsm', debug=debug)
703
707
  semver = manually_import_module('semver', venv='mrsm', debug=debug)
704
708
  return (
@@ -724,10 +728,10 @@ def need_update(
724
728
 
725
729
 
726
730
  def get_pip(
727
- venv: Optional[str] = 'mrsm',
728
- color: bool = True,
729
- debug: bool = False,
730
- ) -> bool:
731
+ venv: Optional[str] = 'mrsm',
732
+ color: bool = True,
733
+ debug: bool = False,
734
+ ) -> bool:
731
735
  """
732
736
  Download and run the get-pip.py script.
733
737
 
@@ -747,7 +751,8 @@ def get_pip(
747
751
  A bool indicating success.
748
752
 
749
753
  """
750
- import sys, subprocess
754
+ import sys
755
+ import subprocess
751
756
  from meerschaum.utils.misc import wget
752
757
  from meerschaum.config._paths import CACHE_RESOURCES_PATH
753
758
  from meerschaum.config.static import STATIC_CONFIG
@@ -755,7 +760,7 @@ def get_pip(
755
760
  dest = CACHE_RESOURCES_PATH / 'get-pip.py'
756
761
  try:
757
762
  wget(url, dest, color=False, debug=debug)
758
- except Exception as e:
763
+ except Exception:
759
764
  print(f"Failed to fetch pip from '{url}'. Please install pip and restart Meerschaum.")
760
765
  sys.exit(1)
761
766
  if venv is not None:
@@ -776,6 +781,7 @@ def pip_install(
776
781
  _uninstall: bool = False,
777
782
  _from_completely_uninstall: bool = False,
778
783
  _install_uv_pip: bool = True,
784
+ _use_uv_pip: bool = True,
779
785
  color: bool = True,
780
786
  silent: bool = False,
781
787
  debug: bool = False,
@@ -835,10 +841,7 @@ def pip_install(
835
841
  from meerschaum.utils.warnings import warn
836
842
  if args is None:
837
843
  args = ['--upgrade'] if not _uninstall else []
838
- if color:
839
- ANSI, UNICODE = True, True
840
- else:
841
- ANSI, UNICODE = False, False
844
+ ANSI = True if color else False
842
845
  if check_wheel:
843
846
  have_wheel = venv_contains_package('wheel', venv=venv, debug=debug)
844
847
 
@@ -877,7 +880,8 @@ def pip_install(
877
880
  )
878
881
 
879
882
  use_uv_pip = (
880
- venv_contains_package('uv', venv=None, debug=debug)
883
+ _use_uv_pip
884
+ and venv_contains_package('uv', venv=None, debug=debug)
881
885
  and uv_bin is not None
882
886
  and venv is not None
883
887
  and is_uv_enabled()
@@ -136,7 +136,7 @@ packages['sql'] = {
136
136
  'numpy' : 'numpy>=1.18.5',
137
137
  'pandas' : 'pandas[parquet]>=2.0.1',
138
138
  'pyarrow' : 'pyarrow>=16.1.0',
139
- 'dask' : 'dask[complete]>=2024.5.1',
139
+ 'dask' : 'dask[complete]>=2024.12.1',
140
140
  'partd' : 'partd>=1.4.2',
141
141
  'pytz' : 'pytz',
142
142
  'joblib' : 'joblib>=0.17.0',
@@ -7,7 +7,9 @@ Functions for interacting with the user.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
+
10
11
  import os
12
+ import meerschaum as mrsm
11
13
  from meerschaum.utils.typing import Any, Union, Optional, Tuple, List
12
14
 
13
15
 
@@ -63,9 +65,8 @@ def prompt(
63
65
 
64
66
  """
65
67
  from meerschaum.utils.packages import attempt_import
66
- from meerschaum.utils.formatting import colored, ANSI, CHARSET, highlight_pipes, fill_ansi
68
+ from meerschaum.utils.formatting import ANSI, CHARSET, highlight_pipes, fill_ansi
67
69
  from meerschaum.config import get_config
68
- from meerschaum.config.static import _static_config
69
70
  from meerschaum.utils.misc import filter_keywords
70
71
  from meerschaum.utils.daemon import running_in_daemon
71
72
  noask = check_noask(noask)
@@ -175,8 +176,6 @@ def yes_no(
175
176
  ```
176
177
  """
177
178
  from meerschaum.utils.warnings import error, warn
178
- from meerschaum.utils.formatting import ANSI, UNICODE
179
- from meerschaum.utils.packages import attempt_import
180
179
 
181
180
  default = options[0] if yes else default
182
181
  noask = yes or check_noask(noask)
@@ -195,7 +194,7 @@ def yes_no(
195
194
  success = False
196
195
 
197
196
  if not success:
198
- error(f"Error getting response. Aborting...", stack=False)
197
+ error("Error getting response. Aborting...", stack=False)
199
198
  if answer == "":
200
199
  answer = default
201
200
 
@@ -205,19 +204,20 @@ def yes_no(
205
204
 
206
205
  return answer.lower() == options[0].lower()
207
206
 
207
+
208
208
  def choose(
209
- question: str,
210
- choices: List[Union[str, Tuple[str, str]]],
211
- default: Union[str, List[str], None] = None,
212
- numeric: bool = True,
213
- multiple: bool = False,
214
- as_indices: bool = False,
215
- delimiter: str = ',',
216
- icon: bool = True,
217
- warn: bool = True,
218
- noask: bool = False,
219
- **kw
220
- ) -> Union[str, Tuple[str], None]:
209
+ question: str,
210
+ choices: List[Union[str, Tuple[str, str]]],
211
+ default: Union[str, List[str], None] = None,
212
+ numeric: bool = True,
213
+ multiple: bool = False,
214
+ as_indices: bool = False,
215
+ delimiter: str = ',',
216
+ icon: bool = True,
217
+ warn: bool = True,
218
+ noask: bool = False,
219
+ **kw
220
+ ) -> Union[str, Tuple[str], None]:
221
221
  """
222
222
  Present a list of options and return the user's choice.
223
223
 
@@ -418,8 +418,8 @@ def choose(
418
418
  valid = (len(answers) > 1 or not (len(answers) == 1 and answers[0] is None))
419
419
  for a in answers:
420
420
  if (
421
- not a in {_original for _new, _original in altered_choices.items()}
422
- and not a in _choices
421
+ a not in {_original for _new, _original in altered_choices.items()}
422
+ and a not in _choices
423
423
  and a != default
424
424
  and not noask
425
425
  ):
@@ -428,21 +428,22 @@ def choose(
428
428
  if valid:
429
429
  break
430
430
  if warn:
431
- _warn(f"Please pick a valid choice.", stack=False)
431
+ _warn("Please pick a valid choice.", stack=False)
432
432
 
433
433
  if not multiple:
434
434
  if not numeric:
435
435
  return answer
436
436
  try:
437
437
  _answer = choices[int(answer) - 1]
438
- if as_indices and isinstance(choice, tuple):
438
+ if as_indices and isinstance(_answer, tuple):
439
439
  return _answer[0]
440
440
  return _answer
441
- except Exception as e:
441
+ except Exception:
442
442
  _warn(f"Could not cast answer '{answer}' to an integer.", stacklevel=3)
443
443
 
444
444
  if not numeric:
445
445
  return answers
446
+
446
447
  _answers = []
447
448
  for a in answers:
448
449
  try:
@@ -451,17 +452,17 @@ def choose(
451
452
  if isinstance(_answer_to_return, tuple) and as_indices:
452
453
  _answer_to_return = _answer_to_return[0]
453
454
  _answers.append(_answer_to_return)
454
- except Exception as e:
455
+ except Exception:
455
456
  _warn(f"Could not cast answer '{a}' to an integer.", stacklevel=3)
456
457
  return _answers
457
458
 
458
459
 
459
460
  def get_password(
460
- username: Optional[str] = None,
461
- minimum_length: Optional[int] = None,
462
- confirm: bool = True,
463
- **kw: Any
464
- ) -> str:
461
+ username: Optional[str] = None,
462
+ minimum_length: Optional[int] = None,
463
+ confirm: bool = True,
464
+ **kw: Any
465
+ ) -> str:
465
466
  """
466
467
  Prompt the user for a password.
467
468
 
@@ -493,15 +494,15 @@ def get_password(
493
494
  from meerschaum.utils.warnings import warn
494
495
  while True:
495
496
  password = prompt(
496
- f"Password" + (f" for user '{username}':" if username is not None else ":"),
497
- is_password = True,
497
+ "Password" + (f" for user '{username}':" if username is not None else ":"),
498
+ is_password=True,
498
499
  **kw
499
500
  )
500
501
  if minimum_length is not None and len(password) < minimum_length:
501
502
  warn(
502
503
  "Password is too short. " +
503
504
  f"Please enter a password that is at least {minimum_length} characters.",
504
- stack = False
505
+ stack=False
505
506
  )
506
507
  continue
507
508
 
@@ -509,12 +510,12 @@ def get_password(
509
510
  return password
510
511
 
511
512
  _password = prompt(
512
- f"Confirm password" + (f" for user '{username}':" if username is not None else ":"),
513
- is_password = True,
513
+ "Confirm password" + (f" for user '{username}':" if username is not None else ":"),
514
+ is_password=True,
514
515
  **kw
515
516
  )
516
517
  if password != _password:
517
- warn(f"Passwords do not match! Please try again.", stack=False)
518
+ warn("Passwords do not match! Please try again.", stack=False)
518
519
  continue
519
520
  else:
520
521
  return password
@@ -550,13 +551,13 @@ def get_email(username: Optional[str] = None, allow_omit: bool = True, **kw: Any
550
551
  from meerschaum.utils.misc import is_valid_email
551
552
  while True:
552
553
  email = prompt(
553
- f"Email" + (f" for user '{username}'" if username is not None else "") +
554
+ "Email" + (f" for user '{username}'" if username is not None else "") +
554
555
  (" (empty to omit):" if allow_omit else ": "),
555
556
  **kw
556
557
  )
557
558
  if (allow_omit and email == '') or is_valid_email(email):
558
559
  return email
559
- warn(f"Invalid email! Please try again.", stack=False)
560
+ warn("Invalid email! Please try again.", stack=False)
560
561
 
561
562
 
562
563
  def check_noask(noask: bool = False) -> bool:
@@ -571,3 +572,20 @@ def check_noask(noask: bool = False) -> bool:
571
572
  os.environ.get(NOASK, 'false').lower()
572
573
  in ('1', 'true')
573
574
  )
575
+
576
+
577
+ def get_connectors_completer(*types: str):
578
+ """
579
+ Return a prompt-toolkit Completer object to pass into `prompt()`.
580
+ """
581
+ from meerschaum.utils.misc import get_connector_labels
582
+ prompt_toolkit_completion = mrsm.attempt_import('prompt_toolkit.completion', lazy=False)
583
+ Completer = prompt_toolkit_completion.Completer
584
+ Completion = prompt_toolkit_completion.Completion
585
+
586
+ class ConnectorCompleter(Completer):
587
+ def get_completions(self, document, complete_event):
588
+ for label in get_connector_labels(*types):
589
+ yield Completion(label, start_position=(-1 * len(document.text)))
590
+
591
+ return ConnectorCompleter()
@@ -410,7 +410,7 @@ def init_venv(
410
410
  pass
411
411
 
412
412
  def wait_for_lock():
413
- max_lock_seconds = 1.0
413
+ max_lock_seconds = 2.0
414
414
  step_sleep_seconds = 0.1
415
415
  init_venv_check_start = time.perf_counter()
416
416
  while ((time.perf_counter() - init_venv_check_start) < max_lock_seconds):
@@ -450,13 +450,22 @@ def init_venv(
450
450
  temp_vtp = VENVS_CACHE_RESOURCES_PATH / str(venv)
451
451
  rename_vtp = vtp.exists() and not temp_vtp.exists()
452
452
 
453
+ wait_for_lock()
454
+ update_lock(True)
455
+
453
456
  if rename_vtp:
454
457
  if debug:
455
458
  print(f"Moving '{vtp}' to '{temp_vtp}'...")
456
459
  shutil.move(vtp, temp_vtp)
457
460
 
458
- wait_for_lock()
459
- update_lock(True)
461
+ if venv_path.exists():
462
+ if debug:
463
+ print(f"Removing '{venv_path}'...")
464
+ try:
465
+ shutil.rmtree(venv_path)
466
+ except Exception as e:
467
+ if debug:
468
+ print(f"Failed to remove '{venv_path}' ({e}). Continuing...")
460
469
 
461
470
  if uv is not None:
462
471
  _venv_success = run_python_package(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: meerschaum
3
- Version: 2.7.5
3
+ Version: 2.7.6
4
4
  Summary: Sync Time-Series Pipes with Meerschaum
5
5
  Home-page: https://meerschaum.io
6
6
  Author: Bennett Meares
@@ -127,7 +127,7 @@ Provides-Extra: sql
127
127
  Requires-Dist: numpy>=1.18.5; extra == "sql"
128
128
  Requires-Dist: pandas[parquet]>=2.0.1; extra == "sql"
129
129
  Requires-Dist: pyarrow>=16.1.0; extra == "sql"
130
- Requires-Dist: dask[complete]>=2024.5.1; extra == "sql"
130
+ Requires-Dist: dask[complete]>=2024.12.1; extra == "sql"
131
131
  Requires-Dist: partd>=1.4.2; extra == "sql"
132
132
  Requires-Dist: pytz; extra == "sql"
133
133
  Requires-Dist: joblib>=0.17.0; extra == "sql"
@@ -187,7 +187,7 @@ Requires-Dist: valkey>=6.0.0; extra == "api"
187
187
  Requires-Dist: numpy>=1.18.5; extra == "api"
188
188
  Requires-Dist: pandas[parquet]>=2.0.1; extra == "api"
189
189
  Requires-Dist: pyarrow>=16.1.0; extra == "api"
190
- Requires-Dist: dask[complete]>=2024.5.1; extra == "api"
190
+ Requires-Dist: dask[complete]>=2024.12.1; extra == "api"
191
191
  Requires-Dist: partd>=1.4.2; extra == "api"
192
192
  Requires-Dist: pytz; extra == "api"
193
193
  Requires-Dist: joblib>=0.17.0; extra == "api"
@@ -292,7 +292,7 @@ Requires-Dist: pycparser>=2.21.0; extra == "full"
292
292
  Requires-Dist: numpy>=1.18.5; extra == "full"
293
293
  Requires-Dist: pandas[parquet]>=2.0.1; extra == "full"
294
294
  Requires-Dist: pyarrow>=16.1.0; extra == "full"
295
- Requires-Dist: dask[complete]>=2024.5.1; extra == "full"
295
+ Requires-Dist: dask[complete]>=2024.12.1; extra == "full"
296
296
  Requires-Dist: partd>=1.4.2; extra == "full"
297
297
  Requires-Dist: pytz; extra == "full"
298
298
  Requires-Dist: joblib>=0.17.0; extra == "full"
@@ -12,8 +12,8 @@ meerschaum/_internal/gui/app/__init__.py,sha256=rKUa8hHk6Fai-PDF61tQcpT1myxKcfmv
12
12
  meerschaum/_internal/gui/app/_windows.py,sha256=-VHdjTzA3V596fVqnbmTxemONSp_80-sTNJ0CTB8FwU,2632
13
13
  meerschaum/_internal/gui/app/actions.py,sha256=rx37qXf3uoa7Ou0n1cISqNFZNL0nr4wO7vSUmWO8f2E,935
14
14
  meerschaum/_internal/gui/app/pipes.py,sha256=4nAQ0rrHb_2bNgDF0Ru2YlbPaCDDzAl5beOGU4Af-4A,1596
15
- meerschaum/_internal/shell/Shell.py,sha256=-dw1k9NbG0VGX0Sve1c8gQ1_XsMYcmYl0VwSO98ERVk,40099
16
- meerschaum/_internal/shell/ShellCompleter.py,sha256=uWo-SYBXDGEeKExsjVWi-u7yfnc5XWWCy4Nl4eSO8j4,3340
15
+ meerschaum/_internal/shell/Shell.py,sha256=R6xW-D9gVuxJxQzf4Bf6E9V8exE40aCdrDJ_snUpoxA,39982
16
+ meerschaum/_internal/shell/ShellCompleter.py,sha256=Ex6mPv83RUNdC3ufRJCcaoOmQ8q8z6tCHDVzXQmWIpY,3293
17
17
  meerschaum/_internal/shell/ValidAutoSuggest.py,sha256=bARjOWMidz0dvMelLUe6yRPto5l3gcEHYHqFDjoh22I,1280
18
18
  meerschaum/_internal/shell/__init__.py,sha256=vXQoQPEVlYiUYai1b5AwQAlTnja6A2cSABnqXhzlS7I,281
19
19
  meerschaum/_internal/shell/updates.py,sha256=FmKu1NsIE7AI1zq8zNeKneZzORv6BeURQeX0lRR81Ag,5040
@@ -25,8 +25,8 @@ meerschaum/actions/__init__.py,sha256=MHPs8aRBhbZQXnqd_6tVtisTrNCgPAPgnNcXYbn0zP
25
25
  meerschaum/actions/api.py,sha256=41r3fBh3vAPyNaOrvbh2oh6WUJTR2I-zaOEZN60A66E,12538
26
26
  meerschaum/actions/attach.py,sha256=UV19d9W_2WYcrf7BRz7k3mriDoX1V4rA4AKvbLdor0o,3106
27
27
  meerschaum/actions/bootstrap.py,sha256=08o3PchrJ_Rv8IP30ZBH1Ovk-b8qFBGPedCjF7jRzSo,18084
28
- meerschaum/actions/clear.py,sha256=iTSdJpFIGLirFgBrOFb2GH1ShI2LZ1NIGLeGYOboZYQ,4916
29
- meerschaum/actions/copy.py,sha256=NHoC9cHJGgoox8L8B0afbu8lAxEh_MKa_pNeVunZsl0,6824
28
+ meerschaum/actions/clear.py,sha256=v_xHn7-Pu7iwFNJ07q9eJt2hqPV7OwNZHUYa9dvixs4,4976
29
+ meerschaum/actions/copy.py,sha256=z_51zEQCKDXnAGfICIGKS3klZ2OTPdiZPJACvpuheDY,6861
30
30
  meerschaum/actions/deduplicate.py,sha256=puYyxeFYEUy1Sd2IOcZB2e6MrNxAZl2bTLmNzFDkCiw,1167
31
31
  meerschaum/actions/delete.py,sha256=H5oP0nE7qIWnFvkuFhZQZQYBVC0IbUevpaQ_2YQKXRA,18559
32
32
  meerschaum/actions/drop.py,sha256=Hd5h4rrWd7qL2rTqglsTonUsEoH7qQlsfqNFSHGeqr0,2453
@@ -46,7 +46,7 @@ meerschaum/actions/sql.py,sha256=zG-KydYR654RHaF-O4Id3ACCDWeogk2B1R-OFLwFbG0,451
46
46
  meerschaum/actions/stack.py,sha256=ZwrCTGJ0x3jjZkRieWcvqasQHYCqNtB1HYvTX-r3Z3g,5996
47
47
  meerschaum/actions/start.py,sha256=NtdVzeB00PQBnDSUSu8ypHmMrZT8_Idmw5BfVZ--Zic,21296
48
48
  meerschaum/actions/stop.py,sha256=5fdUw70YN-yuUWrC-NhA88cxr9FZ5NbssbQ8xXO8nFU,4632
49
- meerschaum/actions/sync.py,sha256=QGhf0ZyrNaplPL6TkwHO9VQLEu_Gemmid93vdaovXoo,17153
49
+ meerschaum/actions/sync.py,sha256=br87b8uqpv7GW18f_O7Zg7QioPh0t377J082yfmuSak,17223
50
50
  meerschaum/actions/tag.py,sha256=SJf5qFW0ccLXjqlTdkK_0MCcrCMdg6xhYrhKdco0hdA,3053
51
51
  meerschaum/actions/uninstall.py,sha256=tBXhdXggSieGEQe4EPGxpgMK0MZTJCweNvAJ9-59El0,5776
52
52
  meerschaum/actions/upgrade.py,sha256=AjuC93Te-I_GWwIfuNkFJ2q1zVHDQ2Oco34S4JgK2iA,6485
@@ -62,7 +62,7 @@ meerschaum/api/dash/connectors.py,sha256=-Wd40ieYJI2nOASXi4V1C4bvLekjnN_tj6zp7Hg
62
62
  meerschaum/api/dash/graphs.py,sha256=wJUDWzcLN8-C3xko6rj0F2v7Rt8YDkSXoVkkXJjYGIk,2046
63
63
  meerschaum/api/dash/jobs.py,sha256=mj9STE6AaQY4fwkjD1JcYRG0iW3VEcP04bO1SlKgiXw,7681
64
64
  meerschaum/api/dash/keys.py,sha256=hzEVeN60SAfVTVSO5lajGaykxRIKGhj9Ph00HRJnNoE,12598
65
- meerschaum/api/dash/pipes.py,sha256=39Ler1YIxaDmbZu9zKuJclA-j9psbrPRwZfBnh4KuxA,26264
65
+ meerschaum/api/dash/pipes.py,sha256=Zm2UKovwz6K8Mt6dTCY2LgDyUyFhEZ5D8nWw4ecPUXI,26210
66
66
  meerschaum/api/dash/plugins.py,sha256=KdfG04f6SsUpBg-nm7MUJegFGuElOj-GAkxDX98hi60,3768
67
67
  meerschaum/api/dash/sessions.py,sha256=-y5p4MYKh1eFzppkBfMsd6T7-rJs1nYS2-4fbVRAeRA,5029
68
68
  meerschaum/api/dash/sync.py,sha256=9lt7IRdG-fe9gf_ZO_viPiGlerX7ic6r_VFocv3I51A,504
@@ -132,7 +132,7 @@ meerschaum/api/routes/_webterm.py,sha256=MenDvWXnZ8CWEmryB46pKohMf0PN6o1xJGZ3LFj
132
132
  meerschaum/api/tables/__init__.py,sha256=e2aNC0CdlWICTUMx1i9RauF8Pm426J0RZJbsJWv4SWo,482
133
133
  meerschaum/config/__init__.py,sha256=5ZBq71P9t3nb74r5CGvMfNuauPscfegBX-nkaAUi5C4,11541
134
134
  meerschaum/config/_dash.py,sha256=BJHl4xMrQB-YHUEU7ldEW8q_nOPoIRSOqLrfGElc6Dw,187
135
- meerschaum/config/_default.py,sha256=IDRo8nLWija_cawiqeS6cPwZ9deDF9179m_rwGntNLA,5831
135
+ meerschaum/config/_default.py,sha256=6SC7MOkU_2oJ7RtFXQCz9w1Qqg2_8w5UdOaR_HL3lzI,6009
136
136
  meerschaum/config/_edit.py,sha256=M9yX_SDD24gV5kWITZpy7p9AWTizJsIAGWAs3WZx-Ws,9087
137
137
  meerschaum/config/_environment.py,sha256=Vv4DLDfc2vKLbCLsMvkQDj77K4kEvHKEBmUBo-wCrgo,4419
138
138
  meerschaum/config/_formatting.py,sha256=OMuqS1EWOsj_34wSs2tOqGIWci3bTMIZ5l-uelZgsIM,6672
@@ -143,7 +143,7 @@ meerschaum/config/_preprocess.py,sha256=-AEA8m_--KivZwTQ1sWN6LTn5sio_fUr2XZ51BO6
143
143
  meerschaum/config/_read_config.py,sha256=RLC3HHi_1ndj7ITVDKLD9_uULY3caGRwSz3ATYE-ixA,15014
144
144
  meerschaum/config/_shell.py,sha256=46_m49Txc5q1rGfCgO49ca48BODx45DQJi8D0zz1R18,4245
145
145
  meerschaum/config/_sync.py,sha256=jHcWRkxd82_BgX8Xo8agsWvf7BSbv3qHLWmYl6ehp_0,4242
146
- meerschaum/config/_version.py,sha256=FtGr91JvNFrz0tCWU-8xhZY04Aon0uXjcSuAPXv1SUI,71
146
+ meerschaum/config/_version.py,sha256=EePnAdxzJgKO-MgeMY2aPKqoD0YcmJBjbRii3glP9Q4,71
147
147
  meerschaum/config/paths.py,sha256=JjibeGN3YAdSNceRwsd42aNmeUrIgM6ndzC8qZAmNI0,621
148
148
  meerschaum/config/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
149
  meerschaum/config/stack/__init__.py,sha256=2UukC0Lmk-aVL1o1qXzumqmuIrw3vu9fD7iCuz4XD4I,10544
@@ -162,23 +162,23 @@ meerschaum/connectors/api/_actions.py,sha256=gd3F8i5BvN8XRvMcPvPVR8sc1DeLzgoBHdD
162
162
  meerschaum/connectors/api/_fetch.py,sha256=Khq9AFr1nk8Dsmcedb77aWhAuHw0JGgVeahDG95Q5MQ,2072
163
163
  meerschaum/connectors/api/_jobs.py,sha256=N5lpHFGG10jlVgaJeWAOTuLBQw3AdgjXsEPpp1YwZQE,11270
164
164
  meerschaum/connectors/api/_login.py,sha256=5GsD-B214vr5EYfM3XrTUs1sTFApxZA-9dNxq8oNSyg,2050
165
- meerschaum/connectors/api/_misc.py,sha256=OZRZBYOokKIEjmQaR8jUYgu6ZRn9VzXBChzR8CfDv_w,1092
166
- meerschaum/connectors/api/_pipes.py,sha256=dGs5rS7qoX4-qw-KTw-_a9b9EtLmLCC-ZKm03ZGts6Q,21263
165
+ meerschaum/connectors/api/_misc.py,sha256=XK0LLexNUEKZjAAqoJ-9oOgwLlMdwxSOvcpqO5NuOas,1083
166
+ meerschaum/connectors/api/_pipes.py,sha256=hk6Qj3tgog8naxl0Y2l6TfJsG4AZmel3bFIaLxuy0XY,21248
167
167
  meerschaum/connectors/api/_plugins.py,sha256=z04tPjfZZWwa7T60mogZH3X3wDmeLdnoN5Oh8m_YsU8,5217
168
168
  meerschaum/connectors/api/_request.py,sha256=Wc4Y70t0VxEj3_ch5fAeeoSAeFMuRnyNLOV-aUFInjY,6996
169
169
  meerschaum/connectors/api/_uri.py,sha256=HWxqGx4R1cHZ3ywy9Ro9ePbFxxusw4RLaC3hpGt9Z6I,1469
170
170
  meerschaum/connectors/api/_users.py,sha256=kzb7ENgXwQ19OJYKOuuWzx2rwVuUZCly9dTnyvVuT2Q,5275
171
171
  meerschaum/connectors/plugin/PluginConnector.py,sha256=aQ1QaB7MordCFimZqoGLb0R12PfDUN_nWks2J5mzeAs,2084
172
172
  meerschaum/connectors/plugin/__init__.py,sha256=pwF7TGY4WNz2_HaVdmK4rPQ9ZwTOEuPHgzOqsGcoXJw,198
173
- meerschaum/connectors/sql/_SQLConnector.py,sha256=g9SFK30CZp7CTJI-SdpOanL1NQUBFQeUng7FSGacJA4,11985
173
+ meerschaum/connectors/sql/_SQLConnector.py,sha256=uyGoCshgL-u6j3VbCDiBJn8LkVuveLeE62y8MWxSo24,12015
174
174
  meerschaum/connectors/sql/__init__.py,sha256=3cqYiDkVasn7zWdtOTAZbT4bo95AuvGOmDD2TkaAxtw,205
175
175
  meerschaum/connectors/sql/_cli.py,sha256=VqAHkdXC0HVXuHaZik2q-cTVmIsuS4DWMcPMJPP_g-Q,4514
176
176
  meerschaum/connectors/sql/_create_engine.py,sha256=RzJz4Qc43P4JS6tkgVvAhbdjEejIepWbxymIfVZ44Nk,10555
177
177
  meerschaum/connectors/sql/_fetch.py,sha256=GOU1JnPOBgaI3dDr0JdAmfTMPLIMM0EFHrsqDgDIO74,14070
178
178
  meerschaum/connectors/sql/_instance.py,sha256=mmZnodccuCqmZN-UnznnFZ7JodxtT47kwjDDaDKgwUg,6274
179
- meerschaum/connectors/sql/_pipes.py,sha256=n0tHoVnBmno08qqO5qaFuSlfIW96_VVm8T1k5ZRdPQw,121592
179
+ meerschaum/connectors/sql/_pipes.py,sha256=M0VQqkwd9sSyyttyKxonjoGi61guVc-oa1KiuWS7sd8,122315
180
180
  meerschaum/connectors/sql/_plugins.py,sha256=wbxcNxqTtjfDsxPvdVGTllasYf6NHHzODaQ72hEUSBQ,8135
181
- meerschaum/connectors/sql/_sql.py,sha256=Q4MKuUlqrgXuYCbpCtoQlvqOvASDQ7BkkLLSYPLh_JE,41052
181
+ meerschaum/connectors/sql/_sql.py,sha256=brYLHJFt6BYlFYUhK--4okkll7UTkRR_PnvjjIJvXNY,41289
182
182
  meerschaum/connectors/sql/_uri.py,sha256=0BrhQtqQdzg9mR04gWBZINs_BbPFtSlTECXT_TCUwik,3460
183
183
  meerschaum/connectors/sql/_users.py,sha256=FJjYeJGhr-TDHziNc6p_5mupGRtGjezKPIYgHFEVSnY,9956
184
184
  meerschaum/connectors/sql/tools.py,sha256=jz8huOaRCwGlYdtGfAqAh7SoK8uydYBrasKQba9FT38,187
@@ -211,33 +211,33 @@ meerschaum/core/Plugin/__init__.py,sha256=UXg64EvJPgI1PCxkY_KM02-ZmBm4FZpLPIQR_u
211
211
  meerschaum/core/User/_User.py,sha256=qbI0GIkr3G0PI4d9S49uatbJQ2kH_-z5-GoVJ0fuEtA,6624
212
212
  meerschaum/core/User/__init__.py,sha256=9qNy-Gobui4x6GiaE8U7-WOggsdniOM3_wegLN3SVKs,988
213
213
  meerschaum/jobs/_Executor.py,sha256=qM62BhFTM4tyJ7p90KOM0y3qyeRY9k3ZV_aTDJMHnO8,1682
214
- meerschaum/jobs/_Job.py,sha256=wRsmrQ1bm898BxXELbHTltKYBj0bK0GmegE8zeL0FG8,32161
214
+ meerschaum/jobs/_Job.py,sha256=m_OzHG1zdV3jBS1CS6idT-sc5XBx-sMz4CJZbWKeKqI,32217
215
215
  meerschaum/jobs/__init__.py,sha256=YjwB6t8HCT593ckrOlImgk0kLX-1NgAYzNXVwS-uvyY,12173
216
216
  meerschaum/jobs/systemd.py,sha256=Rq-tsDPslG17ZhpKMrVJ5r8Z0IPr6DEc9APObfIoXCg,24614
217
217
  meerschaum/plugins/_Plugin.py,sha256=bIo4HX8TTWIcwIHROwMt4VK6OoEUhY_3Qc8q-2dp-ZA,33895
218
- meerschaum/plugins/__init__.py,sha256=6krcqaMKyzuVqesXMqEL0XEy2SJQ4xfNt2-oI_fJ6v0,26278
218
+ meerschaum/plugins/__init__.py,sha256=Kl7Dz0CwUUxyjRC5RWnYo6WMLsOvdX2eQ38Rh3BjdzY,26465
219
219
  meerschaum/plugins/bootstrap.py,sha256=VwjpZAuYdqPJW0YoVgAoM_taHkdQHqP902-8T7OWWCI,11339
220
220
  meerschaum/utils/__init__.py,sha256=QrK1K9hIbPCRCM5k2nZGFqGnrqhA0Eh-iSmCU7FG6Cs,612
221
221
  meerschaum/utils/_get_pipes.py,sha256=tu4xKPoDn79Dz2kWM13cXTP4DSCkn-3G9M8KiLftopw,11073
222
222
  meerschaum/utils/dataframe.py,sha256=fM8_DxnMTMhXDUqWIVXR-bOOwzBGO-cRcjarOIN3jdQ,47990
223
223
  meerschaum/utils/debug.py,sha256=GyIzJmunkoPnOcZNYVQdT4Sgd-aOb5MI2VbIgATOjIQ,3695
224
224
  meerschaum/utils/interactive.py,sha256=t-6jWozXSqL7lYGDHuwiOjTgr-UKhdcg61q_eR5mikI,3196
225
- meerschaum/utils/misc.py,sha256=RW_WmNtAieP828OtJhr4dHKTQI2nxc4kTwn-Q5N3YBw,47055
225
+ meerschaum/utils/misc.py,sha256=Ut__DxYXuu-WtF9Mg2Z1CrnQMBmhPuqGsjOgiZMhAww,47079
226
226
  meerschaum/utils/networking.py,sha256=Sr_eYUGW8_UV9-k9LqRFf7xLtbUcsDucODyLCRsFRUc,1006
227
227
  meerschaum/utils/pool.py,sha256=vkE42af4fjrTEJTxf6Ek3xGucm1MtEkpsSEiaVzNKHs,2655
228
228
  meerschaum/utils/process.py,sha256=9O8PPPJjY9Q5W2f39I3B3lFU6TlSiRiI3bgrzdOOyOw,7843
229
- meerschaum/utils/prompt.py,sha256=SOpAvHcVFuk7-J4cqK_LkahWo6oJmLobeHg5fwM_9aY,18949
229
+ meerschaum/utils/prompt.py,sha256=qbS8l0DfD6eRB9_RRbfkKLPs3m-Hw2zXSeQCf0TDJgU,19370
230
230
  meerschaum/utils/schedule.py,sha256=bUsaCO9CGn2vJO5UvoISScHDDGIiMdCPHxpTFmu7vwE,11531
231
231
  meerschaum/utils/sql.py,sha256=JqOfWCHWAlm1fr7mtZMquoGCOnPyIlX5LDshcRFDgdo,77993
232
232
  meerschaum/utils/threading.py,sha256=awjbVL_QR6G-o_9Qk85utac9cSdqkiC8tQSdERCdrG8,2814
233
233
  meerschaum/utils/typing.py,sha256=U3MC347sh1umpa3Xr1k71eADyDmk4LB6TnVCpq8dVzI,2830
234
234
  meerschaum/utils/warnings.py,sha256=n-phr3BftNNgyPnvnXC_VMSjtCvjiCZ-ewmVfcROhkc,6611
235
235
  meerschaum/utils/yaml.py,sha256=PoC1du0pn2hLwTHwL-zuOf_EBWZSbCGOz-P-AZ4BWN0,3901
236
- meerschaum/utils/daemon/Daemon.py,sha256=zxU15r7XJCTU5r5IWdiH9GQEenUFSnV439f0Vq1EzgY,42760
236
+ meerschaum/utils/daemon/Daemon.py,sha256=jNhzpkcR-kXgIQKBqr--cFx6ZhAb0a0sdjnCOUkLEL0,42885
237
237
  meerschaum/utils/daemon/FileDescriptorInterceptor.py,sha256=MJKMO0Syf3d8yWUs6xXcQzg8Ptsuvh2aCRRoglOjusA,5257
238
238
  meerschaum/utils/daemon/RotatingFile.py,sha256=ePm_svjwyFDWh6V1k-bp1RHXCSWlyxDtlFu4SU4XvPU,24369
239
239
  meerschaum/utils/daemon/StdinFile.py,sha256=qdZ8E_RSOkURypwnS50mWeyWyRig1bAY9tKWMTVKajc,3307
240
- meerschaum/utils/daemon/__init__.py,sha256=o9jWb4lRTIyny4EPt7fPXFgV_vIf1mUofsTwoE1ZecA,8751
240
+ meerschaum/utils/daemon/__init__.py,sha256=ziRPyu_IM3l7Xd58y3Uvt0fZLoirJ9nuboFIxxult6c,8741
241
241
  meerschaum/utils/daemon/_names.py,sha256=d2ZwTxBoTAqXZkCfZ5LuX2XrkQmLNUq1OTlUqfoH5dA,4515
242
242
  meerschaum/utils/dtypes/__init__.py,sha256=c6DoYyCbWvMdRapBRKP5UJYLRUWtkTIlC_8HRzXFh2s,12166
243
243
  meerschaum/utils/dtypes/sql.py,sha256=Ew-ULDAJipzWpq_W-3fGGgTORhtoIqRZzZcS7k0L4B4,19582
@@ -246,16 +246,16 @@ meerschaum/utils/formatting/_jobs.py,sha256=izsqPJhTtUkXUUtWnbXtReYsUYwulXtci3pB
246
246
  meerschaum/utils/formatting/_pipes.py,sha256=OISJmmFiilaDbZxkiXck_g39MnnTfk_fJJyJ-YInvXA,19559
247
247
  meerschaum/utils/formatting/_pprint.py,sha256=tgrT3FyGyu5CWJYysqK3kX1xdZYorlbOk9fcU_vt9Qg,3096
248
248
  meerschaum/utils/formatting/_shell.py,sha256=XH7VFLteNv7NGtWhJl7FdIGt80sKeTiDoJokGSDAwBM,3761
249
- meerschaum/utils/packages/__init__.py,sha256=vg1C9dpj1MLOWgvNGrKkqLRe4Z9hUnNdQDOCvReCBh4,64392
250
- meerschaum/utils/packages/_packages.py,sha256=ykannoLv2Fm4iwZwiIlNAGZvt654cMJhjXr1VJPoEDo,8867
249
+ meerschaum/utils/packages/__init__.py,sha256=TdKaj2tmN4bFwzusOfMv24P5ET7Zv73vyoOf9GOIr5E,64427
250
+ meerschaum/utils/packages/_packages.py,sha256=_xODMSz1FAcx3XHrn9RXUhGJ1zg-QKsVu9zYZV2UJeY,8868
251
251
  meerschaum/utils/packages/lazy_loader.py,sha256=VHnph3VozH29R4JnSSBfwtA5WKZYZQFT_GeQSShCnuc,2540
252
252
  meerschaum/utils/venv/_Venv.py,sha256=gc1TCeAj-kTZbQFAT9xl1bi4HXFV5ApT0dPOJfxwr78,3748
253
- meerschaum/utils/venv/__init__.py,sha256=wqjp0ocIkp6nsHYLUObXIhfYY5CjX-JnS6psm783ga0,26755
254
- meerschaum-2.7.5.dist-info/LICENSE,sha256=jG2zQEdRNt88EgHUWPpXVWmOrOduUQRx7MnYV9YIPaw,11359
255
- meerschaum-2.7.5.dist-info/METADATA,sha256=kQOkmZPuhuo-Ee1b_2JlzUnmfGYOZOBBUWs3pHZ_g1M,24224
256
- meerschaum-2.7.5.dist-info/NOTICE,sha256=OTA9Fcthjf5BRvWDDIcBC_xfLpeDV-RPZh3M-HQBRtQ,114
257
- meerschaum-2.7.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
258
- meerschaum-2.7.5.dist-info/entry_points.txt,sha256=5YBVzibw-0rNA_1VjB16z5GABsOGf-CDhW4yqH8C7Gc,88
259
- meerschaum-2.7.5.dist-info/top_level.txt,sha256=bNoSiDj0El6buocix-FRoAtJOeq1qOF5rRm2u9i7Q6A,11
260
- meerschaum-2.7.5.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
261
- meerschaum-2.7.5.dist-info/RECORD,,
253
+ meerschaum/utils/venv/__init__.py,sha256=vVU9vj7t-HTiRU--ReQZ9kRLesVqcHnSJDbmcfC-Dzg,27030
254
+ meerschaum-2.7.6.dist-info/LICENSE,sha256=jG2zQEdRNt88EgHUWPpXVWmOrOduUQRx7MnYV9YIPaw,11359
255
+ meerschaum-2.7.6.dist-info/METADATA,sha256=fWChi6YW7sc_kNoXq7H3ryE-RdPH0fSR5UsFWQfMhps,24227
256
+ meerschaum-2.7.6.dist-info/NOTICE,sha256=OTA9Fcthjf5BRvWDDIcBC_xfLpeDV-RPZh3M-HQBRtQ,114
257
+ meerschaum-2.7.6.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
258
+ meerschaum-2.7.6.dist-info/entry_points.txt,sha256=5YBVzibw-0rNA_1VjB16z5GABsOGf-CDhW4yqH8C7Gc,88
259
+ meerschaum-2.7.6.dist-info/top_level.txt,sha256=bNoSiDj0El6buocix-FRoAtJOeq1qOF5rRm2u9i7Q6A,11
260
+ meerschaum-2.7.6.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
261
+ meerschaum-2.7.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5