meerschaum 2.8.2__py3-none-any.whl → 2.8.4__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.
- meerschaum/_internal/arguments/_parser.py +5 -0
- meerschaum/actions/drop.py +1 -1
- meerschaum/actions/start.py +14 -6
- meerschaum/actions/sync.py +9 -0
- meerschaum/api/__init__.py +23 -11
- meerschaum/api/routes/_pipes.py +16 -22
- meerschaum/config/_default.py +3 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +1 -1
- meerschaum/connectors/sql/_SQLConnector.py +1 -1
- meerschaum/connectors/sql/_cli.py +7 -1
- meerschaum/connectors/sql/_create_engine.py +6 -3
- meerschaum/connectors/sql/_users.py +4 -2
- meerschaum/core/Pipe/_verify.py +42 -18
- meerschaum/jobs/systemd.py +1 -1
- meerschaum/utils/dataframe.py +1 -1
- meerschaum/utils/packages/_packages.py +1 -1
- meerschaum/utils/process.py +27 -3
- meerschaum/utils/schedule.py +3 -3
- meerschaum/utils/sql.py +1 -1
- meerschaum/utils/venv/__init__.py +4 -1
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/METADATA +1 -1
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/RECORD +29 -29
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/LICENSE +0 -0
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/NOTICE +0 -0
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/WHEEL +0 -0
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/top_level.txt +0 -0
- {meerschaum-2.8.2.dist-info → meerschaum-2.8.4.dist-info}/zip-safe +0 -0
@@ -367,6 +367,11 @@ groups['sync'].add_argument(
|
|
367
367
|
"Only compare row-counts when verifying pipes."
|
368
368
|
),
|
369
369
|
)
|
370
|
+
groups['sync'].add_argument(
|
371
|
+
'--skip-hooks', action='store_true', help=(
|
372
|
+
"Skip calling the sync hooks."
|
373
|
+
)
|
374
|
+
)
|
370
375
|
groups['sync'].add_argument(
|
371
376
|
'--cache', action='store_true',
|
372
377
|
help=(
|
meerschaum/actions/drop.py
CHANGED
meerschaum/actions/start.py
CHANGED
@@ -568,9 +568,9 @@ def _start_pipeline(
|
|
568
568
|
Examples
|
569
569
|
--------
|
570
570
|
|
571
|
-
`sync pipes -i sql:local + sync pipes -i sql:main
|
571
|
+
`sync pipes -i sql:local + sync pipes -i sql:main : -s 'daily'`
|
572
572
|
|
573
|
-
`show version + show arguments
|
573
|
+
`show version + show arguments : --loop`
|
574
574
|
|
575
575
|
"""
|
576
576
|
import json
|
@@ -580,10 +580,11 @@ def _start_pipeline(
|
|
580
580
|
from meerschaum.utils.warnings import info, warn
|
581
581
|
from meerschaum.utils.misc import is_int
|
582
582
|
from meerschaum.utils.venv import venv_exec
|
583
|
-
from meerschaum.utils.process import poll_process
|
583
|
+
from meerschaum.utils.process import poll_process, _stop_process
|
584
584
|
fence_begin, fence_end = '<MRSM_RESULT>', '</MRSM_RESULT>'
|
585
585
|
|
586
|
-
|
586
|
+
default_msg = "Did not pipeline."
|
587
|
+
success, msg = False, default_msg
|
587
588
|
def write_line(line):
|
588
589
|
nonlocal success, msg
|
589
590
|
decoded = line.decode('utf-8')
|
@@ -610,7 +611,9 @@ def _start_pipeline(
|
|
610
611
|
do_n_times = (
|
611
612
|
int(action[0].lstrip('x'))
|
612
613
|
if action and is_int(action[0].lstrip('x'))
|
613
|
-
else
|
614
|
+
else (
|
615
|
+
1 if not loop else -1
|
616
|
+
)
|
614
617
|
)
|
615
618
|
|
616
619
|
params = params or {}
|
@@ -623,8 +626,9 @@ def _start_pipeline(
|
|
623
626
|
if min_seconds is None:
|
624
627
|
min_seconds = 1.0
|
625
628
|
|
629
|
+
proc = None
|
626
630
|
def do_entry() -> None:
|
627
|
-
nonlocal success, msg
|
631
|
+
nonlocal success, msg, proc
|
628
632
|
if timeout_seconds is None:
|
629
633
|
success, msg = entry(sub_args_line, _patch_args=patch_args)
|
630
634
|
return
|
@@ -674,6 +678,10 @@ def _start_pipeline(
|
|
674
678
|
run_loop()
|
675
679
|
except KeyboardInterrupt:
|
676
680
|
warn("Cancelled pipeline.", stack=False)
|
681
|
+
if proc is not None:
|
682
|
+
_stop_process(proc)
|
683
|
+
if msg == default_msg:
|
684
|
+
msg = "Pipeline was cancelled."
|
677
685
|
|
678
686
|
if do_n_times != 1:
|
679
687
|
info(f"Ran pipeline {ran_n_times} time" + ('s' if ran_n_times != 1 else '') + '.')
|
meerschaum/actions/sync.py
CHANGED
@@ -50,6 +50,7 @@ def _pipes_lap(
|
|
50
50
|
bounded: Optional[bool] = None,
|
51
51
|
chunk_interval: Union[timedelta, int, None] = None,
|
52
52
|
check_rowcounts_only: bool = False,
|
53
|
+
skip_hooks: bool = False,
|
53
54
|
mrsm_instance: Optional[str] = None,
|
54
55
|
timeout_seconds: Optional[int] = None,
|
55
56
|
nopretty: bool = False,
|
@@ -95,6 +96,7 @@ def _pipes_lap(
|
|
95
96
|
'bounded': bounded,
|
96
97
|
'chunk_interval': chunk_interval,
|
97
98
|
'check_rowcounts_only': check_rowcounts_only,
|
99
|
+
'skip_hooks': skip_hooks,
|
98
100
|
})
|
99
101
|
locks = {'remaining_count': Lock(), 'results_dict': Lock(), 'pipes_threads': Lock(),}
|
100
102
|
pipes = get_pipes(
|
@@ -257,6 +259,7 @@ def _sync_pipes(
|
|
257
259
|
bounded: Optional[bool] = None,
|
258
260
|
chunk_interval: Union[timedelta, int, None] = None,
|
259
261
|
check_rowcounts_only: bool = False,
|
262
|
+
skip_hooks: bool = False,
|
260
263
|
shell: bool = False,
|
261
264
|
nopretty: bool = False,
|
262
265
|
debug: bool = False,
|
@@ -289,6 +292,8 @@ def _sync_pipes(
|
|
289
292
|
|
290
293
|
noninteractive_val = os.environ.get(STATIC_CONFIG['environment']['noninteractive'], None)
|
291
294
|
noninteractive = str(noninteractive_val).lower() in ('1', 'true', 'yes')
|
295
|
+
if check_rowcounts_only:
|
296
|
+
skip_hooks = True
|
292
297
|
|
293
298
|
run = True
|
294
299
|
msg = ""
|
@@ -312,6 +317,7 @@ def _sync_pipes(
|
|
312
317
|
bounded=bounded,
|
313
318
|
chunk_interval=chunk_interval,
|
314
319
|
check_rowcounts_only=check_rowcounts_only,
|
320
|
+
skip_hooks=skip_hooks,
|
315
321
|
unblock=unblock,
|
316
322
|
debug=debug,
|
317
323
|
nopretty=nopretty,
|
@@ -403,6 +409,7 @@ def _wrap_pipe(
|
|
403
409
|
deduplicate: bool = False,
|
404
410
|
bounded: Optional[bool] = None,
|
405
411
|
chunk_interval: Union[timedelta, int, None] = None,
|
412
|
+
skip_hooks: bool = False,
|
406
413
|
**kw
|
407
414
|
):
|
408
415
|
"""
|
@@ -462,6 +469,8 @@ def _wrap_pipe(
|
|
462
469
|
|
463
470
|
pre_hook_results, post_hook_results = [], []
|
464
471
|
def apply_hooks(is_pre_sync: bool):
|
472
|
+
if skip_hooks:
|
473
|
+
return
|
465
474
|
_sync_hooks = (_pre_sync_hooks if is_pre_sync else _post_sync_hooks)
|
466
475
|
_hook_results = (pre_hook_results if is_pre_sync else post_hook_results)
|
467
476
|
for module_name, sync_hooks in _sync_hooks.items():
|
meerschaum/api/__init__.py
CHANGED
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
9
9
|
|
10
10
|
import os
|
11
11
|
from collections import defaultdict
|
12
|
+
from fnmatch import fnmatch
|
12
13
|
|
13
14
|
import meerschaum as mrsm
|
14
15
|
from meerschaum.utils.typing import Dict, Any, Optional, PipesDict
|
@@ -21,6 +22,7 @@ from meerschaum.plugins import _api_plugins
|
|
21
22
|
from meerschaum.utils.warnings import warn, dprint
|
22
23
|
from meerschaum.utils.threading import RLock
|
23
24
|
from meerschaum.utils.misc import is_pipe_registered
|
25
|
+
from meerschaum.connectors.parse import parse_instance_keys
|
24
26
|
|
25
27
|
from meerschaum import __version__ as version
|
26
28
|
__version__ = version
|
@@ -99,7 +101,6 @@ production = get_uvicorn_config().get('production', False)
|
|
99
101
|
_include_dash = (not no_dash)
|
100
102
|
docs_enabled = not production or sys_config.get('endpoints', {}).get('docs_in_production', True)
|
101
103
|
|
102
|
-
connector = None
|
103
104
|
default_instance_keys = None
|
104
105
|
_instance_connectors = defaultdict(lambda: None)
|
105
106
|
def get_api_connector(instance_keys: Optional[str] = None):
|
@@ -119,23 +120,35 @@ def get_api_connector(instance_keys: Optional[str] = None):
|
|
119
120
|
)
|
120
121
|
|
121
122
|
allowed_instance_keys = permissions_config.get(
|
122
|
-
'
|
123
|
+
'instances', {}
|
123
124
|
).get(
|
124
125
|
'allowed_instance_keys',
|
125
126
|
['*']
|
126
127
|
)
|
127
|
-
|
128
|
+
found_match: bool = False
|
129
|
+
for allowed_keys_pattern in allowed_instance_keys:
|
130
|
+
if fnmatch(instance_keys, allowed_keys_pattern):
|
131
|
+
found_match = True
|
132
|
+
break
|
133
|
+
if not found_match:
|
128
134
|
raise APIPermissionError(
|
129
|
-
f"Instance keys '{instance_keys}' not
|
135
|
+
f"Instance keys '{instance_keys}' does not match the allowed instances patterns."
|
130
136
|
)
|
131
137
|
|
132
138
|
with _locks[f'instance-{instance_keys}']:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
+
if _instance_connectors[instance_keys] is None:
|
140
|
+
try:
|
141
|
+
is_valid_connector = True
|
142
|
+
_instance_connectors[instance_keys] = parse_instance_keys(instance_keys, debug=debug)
|
143
|
+
except Exception:
|
144
|
+
is_valid_connector = False
|
145
|
+
|
146
|
+
if not is_valid_connector:
|
147
|
+
raise fastapi.HTTPException(
|
148
|
+
status_code=422,
|
149
|
+
detail="Invalid instance keys.",
|
150
|
+
)
|
151
|
+
return _instance_connectors[instance_keys]
|
139
152
|
|
140
153
|
|
141
154
|
cache_connector = None
|
@@ -164,7 +177,6 @@ def get_cache_connector(connector_keys: Optional[str] = None):
|
|
164
177
|
return None
|
165
178
|
|
166
179
|
if cache_connector is None:
|
167
|
-
from meerschaum.connectors.parse import parse_instance_keys
|
168
180
|
cache_connector = parse_instance_keys(connector_keys)
|
169
181
|
|
170
182
|
if debug:
|
meerschaum/api/routes/_pipes.py
CHANGED
@@ -272,7 +272,7 @@ async def get_pipes_by_connector_and_metric(
|
|
272
272
|
|
273
273
|
|
274
274
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}', tags=['Pipes'])
|
275
|
-
async def
|
275
|
+
async def get_pipe_by_connector_and_metric_and_location(
|
276
276
|
connector_keys: str,
|
277
277
|
metric_key: str,
|
278
278
|
location_key: str,
|
@@ -299,7 +299,7 @@ async def get_pipes_by_connector_and_metric_and_location(
|
|
299
299
|
detail=f"location_key '{location_key}' not found."
|
300
300
|
)
|
301
301
|
|
302
|
-
return
|
302
|
+
return pipes(instance_keys)[connector_keys][metric_key][location_key].attributes
|
303
303
|
|
304
304
|
|
305
305
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/sync_time', tags=['Pipes'])
|
@@ -311,7 +311,7 @@ def get_sync_time(
|
|
311
311
|
newest: bool = True,
|
312
312
|
remote: bool = False,
|
313
313
|
round_down: bool = True,
|
314
|
-
|
314
|
+
instance_keys: Optional[str] = None,
|
315
315
|
curr_user = (
|
316
316
|
fastapi.Depends(manager) if not no_auth else None
|
317
317
|
),
|
@@ -322,12 +322,11 @@ def get_sync_time(
|
|
322
322
|
"""
|
323
323
|
if location_key == '[None]':
|
324
324
|
location_key = None
|
325
|
-
pipe = get_pipe(connector_keys, metric_key, location_key)
|
325
|
+
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
326
326
|
sync_time = pipe.get_sync_time(
|
327
|
-
params
|
328
|
-
newest
|
329
|
-
|
330
|
-
round_down = round_down,
|
327
|
+
params=params,
|
328
|
+
newest=newest,
|
329
|
+
round_down=round_down,
|
331
330
|
)
|
332
331
|
if isinstance(sync_time, datetime):
|
333
332
|
sync_time = sync_time.isoformat()
|
@@ -339,7 +338,8 @@ def sync_pipe(
|
|
339
338
|
connector_keys: str,
|
340
339
|
metric_key: str,
|
341
340
|
location_key: str,
|
342
|
-
data:
|
341
|
+
data: Union[List[Dict[Any, Any]], Dict[Any, Any]],
|
342
|
+
instance_keys: Optional[str] = None,
|
343
343
|
check_existing: bool = True,
|
344
344
|
blocking: bool = True,
|
345
345
|
force: bool = False,
|
@@ -354,9 +354,9 @@ def sync_pipe(
|
|
354
354
|
Add data to an existing Pipe.
|
355
355
|
See [`meerschaum.Pipe.sync`](https://docs.meerschaum.io/meerschaum.html#Pipe.sync).
|
356
356
|
"""
|
357
|
-
if data
|
358
|
-
data
|
359
|
-
pipe = get_pipe(connector_keys, metric_key, location_key)
|
357
|
+
if not data:
|
358
|
+
return [True, "No data to sync."]
|
359
|
+
pipe = get_pipe(connector_keys, metric_key, location_key, instance_keys)
|
360
360
|
if pipe.target in ('mrsm_users', 'mrsm_plugins', 'mrsm_pipes'):
|
361
361
|
raise fastapi.HTTPException(
|
362
362
|
status_code=409,
|
@@ -365,21 +365,16 @@ def sync_pipe(
|
|
365
365
|
|
366
366
|
if not pipe.columns and columns is not None:
|
367
367
|
pipe.columns = json.loads(columns)
|
368
|
-
if not pipe.columns and not is_pipe_registered(pipe, pipes(refresh=True)):
|
369
|
-
raise fastapi.HTTPException(
|
370
|
-
status_code=409,
|
371
|
-
detail="Pipe must be registered with index columns specified."
|
372
|
-
)
|
373
368
|
|
374
|
-
|
369
|
+
success, msg = pipe.sync(
|
375
370
|
data,
|
376
371
|
debug=debug,
|
377
372
|
check_existing=check_existing,
|
378
373
|
blocking=blocking,
|
379
374
|
force=force,
|
380
375
|
workers=workers,
|
381
|
-
)
|
382
|
-
return
|
376
|
+
)
|
377
|
+
return list((success, msg))
|
383
378
|
|
384
379
|
|
385
380
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/data', tags=['Pipes'])
|
@@ -527,7 +522,6 @@ def get_pipe_csv(
|
|
527
522
|
if params == 'null':
|
528
523
|
params = None
|
529
524
|
if params is not None:
|
530
|
-
import json
|
531
525
|
try:
|
532
526
|
_params = json.loads(params)
|
533
527
|
except Exception:
|
@@ -543,7 +537,7 @@ def get_pipe_csv(
|
|
543
537
|
if not is_pipe_registered(pipe, pipes(instance_keys, refresh=True)):
|
544
538
|
raise fastapi.HTTPException(
|
545
539
|
status_code=409,
|
546
|
-
detail="Pipe must be registered
|
540
|
+
detail="Pipe must be registered."
|
547
541
|
)
|
548
542
|
|
549
543
|
dt_col = pipe.columns.get('datetime', None)
|
meerschaum/config/_default.py
CHANGED
meerschaum/config/_version.py
CHANGED
@@ -184,7 +184,7 @@ class SQLConnector(Connector):
|
|
184
184
|
### ensure flavor and label are set accordingly
|
185
185
|
if 'flavor' not in self.__dict__:
|
186
186
|
if flavor is None and 'uri' not in self.__dict__:
|
187
|
-
raise
|
187
|
+
raise ValueError(
|
188
188
|
f" Missing flavor. Provide flavor as a key for '{self}'."
|
189
189
|
)
|
190
190
|
self.flavor = flavor or self.parse_uri(self.__dict__['uri']).get('flavor', None)
|
@@ -100,7 +100,13 @@ def _cli_exit(
|
|
100
100
|
### yet defined (e.g. 'sql:local').
|
101
101
|
cli_arg_str = self.DATABASE_URL
|
102
102
|
if self.flavor in ('sqlite', 'duckdb'):
|
103
|
-
cli_arg_str =
|
103
|
+
cli_arg_str = (
|
104
|
+
str(self.database)
|
105
|
+
if 'database' in self.__dict__
|
106
|
+
else self.parse_uri(self.URI).get('database', None)
|
107
|
+
)
|
108
|
+
if not cli_arg_str:
|
109
|
+
raise ValueError(f"Cannot determine database from connector '{self}'.")
|
104
110
|
if cli_arg_str.startswith('postgresql+psycopg://'):
|
105
111
|
cli_arg_str = cli_arg_str.replace('postgresql+psycopg://', 'postgresql://')
|
106
112
|
|
@@ -256,8 +256,11 @@ def create_engine(
|
|
256
256
|
) if not _uri else _uri
|
257
257
|
|
258
258
|
### Sometimes the timescaledb:// flavor can slip in.
|
259
|
-
if _uri and self.flavor in
|
260
|
-
|
259
|
+
if _uri and self.flavor in _uri:
|
260
|
+
if self.flavor == 'timescaledb':
|
261
|
+
engine_str = engine_str.replace(f'{self.flavor}', 'postgresql', 1)
|
262
|
+
elif _uri.startswith('postgresql://'):
|
263
|
+
engine_str = engine_str.replace('postgresql://', 'postgresql+psycopg2://')
|
261
264
|
|
262
265
|
if debug:
|
263
266
|
dprint(
|
@@ -303,7 +306,7 @@ def create_engine(
|
|
303
306
|
echo = debug,
|
304
307
|
**_create_engine_args
|
305
308
|
)
|
306
|
-
except Exception
|
309
|
+
except Exception:
|
307
310
|
warn(f"Failed to create connector '{self}':\n{traceback.format_exc()}", stack=False)
|
308
311
|
engine = None
|
309
312
|
|
@@ -43,7 +43,9 @@ def register_user(
|
|
43
43
|
'password_hash': user.password_hash,
|
44
44
|
'user_type': user.type,
|
45
45
|
'attributes': (
|
46
|
-
json.dumps(user.attributes)
|
46
|
+
json.dumps(user.attributes)
|
47
|
+
if self.flavor not in json_flavors
|
48
|
+
else user.attributes
|
47
49
|
),
|
48
50
|
}
|
49
51
|
if old_id is not None:
|
@@ -109,7 +111,7 @@ def edit_user(
|
|
109
111
|
user_id = user.user_id if user.user_id is not None else self.get_user_id(user, debug=debug)
|
110
112
|
if user_id is None:
|
111
113
|
return False, (
|
112
|
-
f"User '{user.username}' does not exist. "
|
114
|
+
f"User '{user.username}' does not exist. "
|
113
115
|
f"Register user '{user.username}' before editing."
|
114
116
|
)
|
115
117
|
user.user_id = user_id
|
meerschaum/core/Pipe/_verify.py
CHANGED
@@ -7,6 +7,7 @@ Verify the contents of a pipe by resyncing its interval.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from datetime import datetime, timedelta
|
10
|
+
import time
|
10
11
|
|
11
12
|
import meerschaum as mrsm
|
12
13
|
from meerschaum.utils.typing import SuccessTuple, Any, Optional, Union, Tuple, Dict
|
@@ -118,7 +119,7 @@ def verify(
|
|
118
119
|
begin, end = self.parse_date_bounds(begin, end)
|
119
120
|
cannot_determine_bounds = bounded and begin is None and end is None
|
120
121
|
|
121
|
-
if cannot_determine_bounds:
|
122
|
+
if cannot_determine_bounds and not check_rowcounts_only:
|
122
123
|
warn(f"Cannot determine sync bounds for {self}. Syncing instead...", stack=False)
|
123
124
|
sync_success, sync_msg = self.sync(
|
124
125
|
begin=begin,
|
@@ -183,9 +184,12 @@ def verify(
|
|
183
184
|
)
|
184
185
|
)
|
185
186
|
message_header = f"{begin_to_print} - {end_to_print}"
|
187
|
+
max_chunks_syncs = mrsm.get_config('pipes', 'verify', 'max_chunks_syncs')
|
186
188
|
|
187
189
|
info(
|
188
|
-
f"Verifying {self}:\n
|
190
|
+
f"Verifying {self}:\n "
|
191
|
+
+ ("Syncing" if not check_rowcounts_only else "Checking")
|
192
|
+
+ f" {len(chunk_bounds)} chunk"
|
189
193
|
+ ('s' if len(chunk_bounds) != 1 else '')
|
190
194
|
+ f" ({'un' if not bounded else ''}bounded)"
|
191
195
|
+ f" of size '{interval_str(chunk_interval)}'"
|
@@ -219,9 +223,9 @@ def verify(
|
|
219
223
|
debug=debug,
|
220
224
|
)
|
221
225
|
checked_rows_str = (
|
222
|
-
f"checked {existing_rowcount} row"
|
226
|
+
f"checked {existing_rowcount:,} row"
|
223
227
|
+ ("s" if existing_rowcount != 1 else '')
|
224
|
-
+ f" vs {remote_rowcount} remote"
|
228
|
+
+ f" vs {remote_rowcount:,} remote"
|
225
229
|
)
|
226
230
|
if (
|
227
231
|
existing_rowcount is not None
|
@@ -239,19 +243,26 @@ def verify(
|
|
239
243
|
f"Row-counts are out-of-sync ({checked_rows_str})."
|
240
244
|
)
|
241
245
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
246
|
+
num_syncs = 0
|
247
|
+
while num_syncs < max_chunks_syncs:
|
248
|
+
chunk_success, chunk_msg = self.sync(
|
249
|
+
begin=chunk_begin,
|
250
|
+
end=chunk_end,
|
251
|
+
params=params,
|
252
|
+
workers=_workers,
|
253
|
+
debug=debug,
|
254
|
+
**kwargs
|
255
|
+
) if do_sync else (chunk_success, chunk_msg)
|
256
|
+
if chunk_success:
|
257
|
+
break
|
258
|
+
num_syncs += 1
|
259
|
+
time.sleep(num_syncs**2)
|
250
260
|
chunk_msg = chunk_msg.strip()
|
251
261
|
if ' - ' not in chunk_msg:
|
252
262
|
chunk_label = f"{chunk_begin} - {chunk_end}"
|
253
263
|
chunk_msg = f'Verified chunk for {self}:\n{chunk_label}\n{chunk_msg}'
|
254
264
|
mrsm.pprint((chunk_success, chunk_msg))
|
265
|
+
|
255
266
|
return chunk_begin_and_end, (chunk_success, chunk_msg)
|
256
267
|
|
257
268
|
### If we have more than one chunk, attempt to sync the first one and return if its fails.
|
@@ -284,6 +295,17 @@ def verify(
|
|
284
295
|
_batch_begin = batch_chunk_bounds[0][0]
|
285
296
|
_batch_end = batch_chunk_bounds[-1][-1]
|
286
297
|
batch_message_header = f"{_batch_begin} - {_batch_end}"
|
298
|
+
|
299
|
+
if check_rowcounts_only:
|
300
|
+
info(f"Checking row-counts for batch bounds:\n {batch_message_header}")
|
301
|
+
_, (batch_init_success, batch_init_msg) = process_chunk_bounds(
|
302
|
+
(_batch_begin, _batch_end)
|
303
|
+
)
|
304
|
+
mrsm.pprint((batch_init_success, batch_init_msg))
|
305
|
+
if batch_init_success and 'up-to-date' in batch_init_msg:
|
306
|
+
info("Entire batch is up-to-date.")
|
307
|
+
return batch_init_success, batch_init_msg
|
308
|
+
|
287
309
|
batch_bounds_success_tuples = dict(pool.map(process_chunk_bounds, batch_chunk_bounds))
|
288
310
|
bounds_success_tuples.update(batch_bounds_success_tuples)
|
289
311
|
batch_bounds_success_bools = {
|
@@ -395,7 +417,7 @@ def verify(
|
|
395
417
|
retry_failed_batch = False
|
396
418
|
|
397
419
|
batch_msg_to_print = (
|
398
|
-
f"{make_header('Completed batch ' + batch_counter_str + '
|
420
|
+
f"{make_header('Completed batch ' + batch_counter_str + ':')}\n{batch_msg}"
|
399
421
|
)
|
400
422
|
mrsm.pprint((batch_success, batch_msg_to_print))
|
401
423
|
|
@@ -471,11 +493,13 @@ def get_chunks_success_message(
|
|
471
493
|
header = (header + "\n") if header else ""
|
472
494
|
stats_msg = items_str(
|
473
495
|
(
|
474
|
-
(
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
496
|
+
(
|
497
|
+
([f'inserted {num_inserted:,}'] if num_inserted else [])
|
498
|
+
+ ([f'updated {num_updated:,}'] if num_updated else [])
|
499
|
+
+ ([f'upserted {num_upserted:,}'] if num_upserted else [])
|
500
|
+
+ ([f'checked {num_checked:,}'] if num_checked else [])
|
501
|
+
) or ['synced 0']
|
502
|
+
),
|
479
503
|
quotes=False,
|
480
504
|
and_=False,
|
481
505
|
)
|
meerschaum/jobs/systemd.py
CHANGED
meerschaum/utils/dataframe.py
CHANGED
@@ -222,7 +222,7 @@ def filter_unseen_df(
|
|
222
222
|
numeric_cols_precisions_scales = {
|
223
223
|
col: get_numeric_precision_scale(None, typ)
|
224
224
|
for col, typ in dtypes.items()
|
225
|
-
if col and typ
|
225
|
+
if col and str(typ).lower().startswith('numeric')
|
226
226
|
}
|
227
227
|
|
228
228
|
dt_dtypes = {
|
@@ -58,7 +58,7 @@ packages: Dict[str, Dict[str, str]] = {
|
|
58
58
|
'_internal' : {
|
59
59
|
'apscheduler' : (
|
60
60
|
f"{_MRSM_PACKAGE_ARCHIVES_PREFIX}"
|
61
|
-
"APScheduler-4.0.0a5.
|
61
|
+
"APScheduler-4.0.0a5.post87+mrsm-py3-none-any.whl>=4.0.0a5"
|
62
62
|
),
|
63
63
|
'dataclass_wizard' : 'dataclass-wizard>=0.28.0',
|
64
64
|
},
|
meerschaum/utils/process.py
CHANGED
@@ -9,15 +9,25 @@ See `meerschaum.utils.pool` for multiprocessing and
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
from __future__ import annotations
|
12
|
-
|
12
|
+
|
13
|
+
import os
|
14
|
+
import signal
|
15
|
+
import subprocess
|
16
|
+
import sys
|
17
|
+
import platform
|
18
|
+
|
19
|
+
import meerschaum as mrsm
|
13
20
|
from meerschaum.utils.typing import Union, Optional, Any, Callable, Dict, Tuple
|
14
21
|
from meerschaum.config.static import STATIC_CONFIG
|
15
22
|
|
16
23
|
_child_processes = []
|
17
24
|
def signal_handler(sig, frame):
|
18
25
|
for child in _child_processes:
|
19
|
-
|
20
|
-
|
26
|
+
try:
|
27
|
+
child.send_signal(sig)
|
28
|
+
child.wait()
|
29
|
+
except Exception:
|
30
|
+
pass
|
21
31
|
|
22
32
|
def run_process(
|
23
33
|
*args,
|
@@ -223,3 +233,17 @@ def poll_process(
|
|
223
233
|
watchdog_thread.cancel()
|
224
234
|
|
225
235
|
return proc.poll()
|
236
|
+
|
237
|
+
|
238
|
+
def _stop_process(
|
239
|
+
proc: subprocess.Popen,
|
240
|
+
timeout_seconds: int = 8,
|
241
|
+
):
|
242
|
+
"""
|
243
|
+
Stop a `subproccess.Popen` object.
|
244
|
+
"""
|
245
|
+
proc.terminate()
|
246
|
+
try:
|
247
|
+
proc.wait(timeout=timeout_seconds)
|
248
|
+
except subprocess.TimeoutExpired:
|
249
|
+
proc.kill()
|
meerschaum/utils/schedule.py
CHANGED
@@ -95,7 +95,7 @@ def schedule_function(
|
|
95
95
|
A `SuccessTuple` upon exit.
|
96
96
|
"""
|
97
97
|
import asyncio
|
98
|
-
from meerschaum.utils.misc import filter_keywords
|
98
|
+
from meerschaum.utils.misc import filter_keywords
|
99
99
|
|
100
100
|
global _scheduler
|
101
101
|
kw['debug'] = debug
|
@@ -103,7 +103,7 @@ def schedule_function(
|
|
103
103
|
|
104
104
|
_ = mrsm.attempt_import('attrs', lazy=False)
|
105
105
|
apscheduler = mrsm.attempt_import('apscheduler', lazy=False)
|
106
|
-
now =
|
106
|
+
now = datetime.now(timezone.utc)
|
107
107
|
trigger = parse_schedule(schedule, now=now)
|
108
108
|
_scheduler = apscheduler.AsyncScheduler(identity='mrsm-scheduler')
|
109
109
|
try:
|
@@ -296,7 +296,7 @@ def parse_start_time(schedule: str, now: Optional[datetime] = None) -> datetime:
|
|
296
296
|
dateutil_parser = mrsm.attempt_import('dateutil.parser')
|
297
297
|
starting_parts = schedule.split(STARTING_KEYWORD)
|
298
298
|
starting_str = ('now' if len(starting_parts) == 1 else starting_parts[-1]).strip()
|
299
|
-
now = now or
|
299
|
+
now = now or datetime.now(timezone.utc)
|
300
300
|
try:
|
301
301
|
if starting_str == 'now':
|
302
302
|
starting_ts = now
|
meerschaum/utils/sql.py
CHANGED
@@ -1548,7 +1548,7 @@ def get_update_queries(
|
|
1548
1548
|
from meerschaum.utils.debug import dprint
|
1549
1549
|
from meerschaum.utils.dtypes import are_dtypes_equal
|
1550
1550
|
from meerschaum.utils.dtypes.sql import DB_FLAVORS_CAST_DTYPES, get_pd_type_from_db_type
|
1551
|
-
flavor = flavor or (connectable
|
1551
|
+
flavor = flavor or getattr(connectable, 'flavor', None)
|
1552
1552
|
if not flavor:
|
1553
1553
|
raise ValueError("Provide a flavor if using a SQLAlchemy session.")
|
1554
1554
|
if (
|
@@ -595,7 +595,7 @@ def venv_exec(
|
|
595
595
|
as_proc: bool = False,
|
596
596
|
capture_output: bool = True,
|
597
597
|
debug: bool = False,
|
598
|
-
) -> Union[bool, Tuple[int, bytes, bytes]]:
|
598
|
+
) -> Union[bool, Tuple[int, bytes, bytes], 'subprocess.Popen']:
|
599
599
|
"""
|
600
600
|
Execute Python code in a subprocess via a virtual environment's interpeter.
|
601
601
|
Return `True` if the code successfully executes, `False` on failure.
|
@@ -630,6 +630,8 @@ def venv_exec(
|
|
630
630
|
import subprocess
|
631
631
|
import platform
|
632
632
|
from meerschaum.utils.debug import dprint
|
633
|
+
from meerschaum.utils.process import _child_processes
|
634
|
+
|
633
635
|
executable = venv_executable(venv=venv)
|
634
636
|
cmd_list = [executable, '-c', code]
|
635
637
|
if env is None:
|
@@ -656,6 +658,7 @@ def venv_exec(
|
|
656
658
|
**group_kwargs
|
657
659
|
)
|
658
660
|
if as_proc:
|
661
|
+
_child_processes.append(process)
|
659
662
|
return process
|
660
663
|
stdout, stderr = process.communicate()
|
661
664
|
exit_code = process.returncode
|
@@ -4,7 +4,7 @@ meerschaum/_internal/__init__.py,sha256=ilC7utfKtin7GAvuN34fKyUQYfPyqH0Mm3MJF5iy
|
|
4
4
|
meerschaum/_internal/entry.py,sha256=Y1m2ar3TWBo_XntPL1P9ehUpjEAfXp2ZGZ-V6r5fXWQ,12438
|
5
5
|
meerschaum/_internal/arguments/__init__.py,sha256=_nSKKVLXNsJeSv-buxEZsx8_c0BAbkhRyE4nT6Bv6q0,541
|
6
6
|
meerschaum/_internal/arguments/_parse_arguments.py,sha256=TtHX7NvdHLD-nVVlMctc6SVULRHXlTgB6sV6UMBEDqY,16430
|
7
|
-
meerschaum/_internal/arguments/_parser.py,sha256=
|
7
|
+
meerschaum/_internal/arguments/_parser.py,sha256=9AfOJ4Kc37y2gLeRabU3cDwF4RRnW-3nGKfN2l0P3rQ,17163
|
8
8
|
meerschaum/_internal/docs/__init__.py,sha256=ZQYHWo6n0kfLLkyG36YXqTYvv2Pc7it5HZHMylT6cBA,126
|
9
9
|
meerschaum/_internal/docs/index.py,sha256=ZkqXj-GhoLEpgMysy4ugvOlFhWVlnq7tFvzMhy43jUQ,24670
|
10
10
|
meerschaum/_internal/gui/__init__.py,sha256=KF6Opae0aBOjIndMZ2txoPs7ozCXRlR-lcTsicLO7fc,1313
|
@@ -29,7 +29,7 @@ meerschaum/actions/clear.py,sha256=v_xHn7-Pu7iwFNJ07q9eJt2hqPV7OwNZHUYa9dvixs4,4
|
|
29
29
|
meerschaum/actions/copy.py,sha256=QmlR_Ky-9SSgCV4Tmd3tgOBF63xchA1iZoEPFCYX8zc,6981
|
30
30
|
meerschaum/actions/deduplicate.py,sha256=puYyxeFYEUy1Sd2IOcZB2e6MrNxAZl2bTLmNzFDkCiw,1167
|
31
31
|
meerschaum/actions/delete.py,sha256=H5oP0nE7qIWnFvkuFhZQZQYBVC0IbUevpaQ_2YQKXRA,18559
|
32
|
-
meerschaum/actions/drop.py,sha256=
|
32
|
+
meerschaum/actions/drop.py,sha256=xNgHWFPyvs4lm923BCRwYJULUqGYMbcVnRPb25Y-lzs,4433
|
33
33
|
meerschaum/actions/edit.py,sha256=VpP6bJ-i7GR3tRzs_PILcDKcFCBeTUaeXpZDwxJ4fFk,16224
|
34
34
|
meerschaum/actions/index.py,sha256=byhcGi7P1S0TTcJPBxq3jGKmBF_gZ8t77oqtg0kGSdI,1826
|
35
35
|
meerschaum/actions/install.py,sha256=P_M2dnn3sVC2mAn5hwvu4VHWkoh4r9TBUzNcU_Kukpc,7437
|
@@ -45,14 +45,14 @@ meerschaum/actions/sh.py,sha256=hSkGNTVqP5dNjhJ64zy3V3VCFPTKnDlH3PxdKdxtkGQ,1990
|
|
45
45
|
meerschaum/actions/show.py,sha256=y-IKxVo9VDg3z_W5VsfEH5unr7EWUo17y-ZhLuYo5LU,28413
|
46
46
|
meerschaum/actions/sql.py,sha256=PhbBMBq20LL8Yh3q-yqGMe7f8ffmyjbD8q_G8Q0WxZc,4527
|
47
47
|
meerschaum/actions/stack.py,sha256=ZwrCTGJ0x3jjZkRieWcvqasQHYCqNtB1HYvTX-r3Z3g,5996
|
48
|
-
meerschaum/actions/start.py,sha256=
|
48
|
+
meerschaum/actions/start.py,sha256=7BPebj698D71ZdlwTG9E-5jLPJ4CeHJ7-XaW3OXoNdY,21927
|
49
49
|
meerschaum/actions/stop.py,sha256=5fdUw70YN-yuUWrC-NhA88cxr9FZ5NbssbQ8xXO8nFU,4632
|
50
|
-
meerschaum/actions/sync.py,sha256=
|
50
|
+
meerschaum/actions/sync.py,sha256=doXa0gQTRoj2X3t3as0_gBCWCO6Dp2x6iujT-5YVvak,17679
|
51
51
|
meerschaum/actions/tag.py,sha256=SJf5qFW0ccLXjqlTdkK_0MCcrCMdg6xhYrhKdco0hdA,3053
|
52
52
|
meerschaum/actions/uninstall.py,sha256=tBXhdXggSieGEQe4EPGxpgMK0MZTJCweNvAJ9-59El0,5776
|
53
53
|
meerschaum/actions/upgrade.py,sha256=AjuC93Te-I_GWwIfuNkFJ2q1zVHDQ2Oco34S4JgK2iA,6485
|
54
54
|
meerschaum/actions/verify.py,sha256=81Km4sPkLVAzPG6pDbMfoBpEWsk8pxjVGXgu-k8seSs,5019
|
55
|
-
meerschaum/api/__init__.py,sha256=
|
55
|
+
meerschaum/api/__init__.py,sha256=UsAFx7oOTB9Z8m1u0DRfiQFdSxjoyqgVaICuwv7loDg,10414
|
56
56
|
meerschaum/api/_chain.py,sha256=h8-WXUGXX6AqzdALfsBC5uv0FkAcLdHJXCGzqzuq89k,875
|
57
57
|
meerschaum/api/_events.py,sha256=f-98AXHU10IL9zRGX1FrZFANxxiMz5ryeJnfFWaU8R8,2232
|
58
58
|
meerschaum/api/_exceptions.py,sha256=xfbWp8F8JYrMUdtDXesn8C8e39_jAXHz51IosIGjkVM,463
|
@@ -126,7 +126,7 @@ meerschaum/api/routes/_index.py,sha256=Z8kuyqm3vmJadw8iIYyswYI4-3IOJ7KXdkhDTv1oU
|
|
126
126
|
meerschaum/api/routes/_jobs.py,sha256=sEt-UtVd5pN-hJgikTvj1oTKJQ2hhNe8XhjkclwOXOE,12568
|
127
127
|
meerschaum/api/routes/_login.py,sha256=tygEp50EVOMgvTG6CEASlShflbtEK8viJ9O07o0lnnE,2434
|
128
128
|
meerschaum/api/routes/_misc.py,sha256=XxfSvXNGAm8rdvXePXWxX8wc5tjeAdBOSZwYveL3oAM,2591
|
129
|
-
meerschaum/api/routes/_pipes.py,sha256=
|
129
|
+
meerschaum/api/routes/_pipes.py,sha256=4cHjGNXKnPQsF7_TZClpTv3QyILLFlgYPKQjxNYCqy8,25247
|
130
130
|
meerschaum/api/routes/_plugins.py,sha256=okstNlv9Bhoiy6JvQWgwjxEi4kQ8adPUcir6k3Y7hH8,6329
|
131
131
|
meerschaum/api/routes/_users.py,sha256=i55LuLTQ2cuzIyWz0PxkWji6aQQUIBPf_FEryKwXI50,7197
|
132
132
|
meerschaum/api/routes/_version.py,sha256=-3A0i4Gk54netFOOwjI_x3YQik9vgHjtq7G_VYbzIJo,750
|
@@ -134,7 +134,7 @@ meerschaum/api/routes/_webterm.py,sha256=S7RXV8vvaTFbmVeehh4UhyXb4NCgcsyOQzoAG7j
|
|
134
134
|
meerschaum/api/tables/__init__.py,sha256=e2aNC0CdlWICTUMx1i9RauF8Pm426J0RZJbsJWv4SWo,482
|
135
135
|
meerschaum/config/__init__.py,sha256=5ZBq71P9t3nb74r5CGvMfNuauPscfegBX-nkaAUi5C4,11541
|
136
136
|
meerschaum/config/_dash.py,sha256=BJHl4xMrQB-YHUEU7ldEW8q_nOPoIRSOqLrfGElc6Dw,187
|
137
|
-
meerschaum/config/_default.py,sha256=
|
137
|
+
meerschaum/config/_default.py,sha256=F1xVug-lhVeIXTL1wvHrIPFmBsL2dGz4lHFakIleeZk,6473
|
138
138
|
meerschaum/config/_edit.py,sha256=M9yX_SDD24gV5kWITZpy7p9AWTizJsIAGWAs3WZx-Ws,9087
|
139
139
|
meerschaum/config/_environment.py,sha256=Vv4DLDfc2vKLbCLsMvkQDj77K4kEvHKEBmUBo-wCrgo,4419
|
140
140
|
meerschaum/config/_formatting.py,sha256=OMuqS1EWOsj_34wSs2tOqGIWci3bTMIZ5l-uelZgsIM,6672
|
@@ -145,7 +145,7 @@ meerschaum/config/_preprocess.py,sha256=-AEA8m_--KivZwTQ1sWN6LTn5sio_fUr2XZ51BO6
|
|
145
145
|
meerschaum/config/_read_config.py,sha256=RLC3HHi_1ndj7ITVDKLD9_uULY3caGRwSz3ATYE-ixA,15014
|
146
146
|
meerschaum/config/_shell.py,sha256=46_m49Txc5q1rGfCgO49ca48BODx45DQJi8D0zz1R18,4245
|
147
147
|
meerschaum/config/_sync.py,sha256=jHcWRkxd82_BgX8Xo8agsWvf7BSbv3qHLWmYl6ehp_0,4242
|
148
|
-
meerschaum/config/_version.py,sha256=
|
148
|
+
meerschaum/config/_version.py,sha256=qo9eC8a6skjLulPkTYodkLffX9t1hvHTg8JGgbZo4Do,71
|
149
149
|
meerschaum/config/paths.py,sha256=JjibeGN3YAdSNceRwsd42aNmeUrIgM6ndzC8qZAmNI0,621
|
150
150
|
meerschaum/config/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
151
151
|
meerschaum/config/stack/__init__.py,sha256=2UukC0Lmk-aVL1o1qXzumqmuIrw3vu9fD7iCuz4XD4I,10544
|
@@ -153,7 +153,7 @@ meerschaum/config/stack/grafana/__init__.py,sha256=LNXQw2FvHKrD68RDhqDmi2wJjAHaK
|
|
153
153
|
meerschaum/config/stack/mosquitto/__init__.py,sha256=-OwOjq8KiBoSH_pmgCAAF3Dp3CRD4KgAEdimZSadROs,186
|
154
154
|
meerschaum/config/stack/mosquitto/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
155
155
|
meerschaum/config/stack/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
156
|
-
meerschaum/config/static/__init__.py,sha256=
|
156
|
+
meerschaum/config/static/__init__.py,sha256=ccm5oaYnLu0j5B85C9a8Y7jWsw4ReJq5RqyvLd-rW_s,5519
|
157
157
|
meerschaum/connectors/_Connector.py,sha256=VaVNg0SlQCTXk4shl3c68QdkbymA2Y9ScUlUjckk8PY,6795
|
158
158
|
meerschaum/connectors/__init__.py,sha256=bpWsnU0uvoowWyUkFTwfEkadK84pssZUJ4M7yReudOU,12703
|
159
159
|
meerschaum/connectors/parse.py,sha256=tnqzkzt_suOXYzktn_XVUrprtfym9ThijUf8HXZZlhY,4194
|
@@ -172,17 +172,17 @@ meerschaum/connectors/api/_uri.py,sha256=HWxqGx4R1cHZ3ywy9Ro9ePbFxxusw4RLaC3hpGt
|
|
172
172
|
meerschaum/connectors/api/_users.py,sha256=kzb7ENgXwQ19OJYKOuuWzx2rwVuUZCly9dTnyvVuT2Q,5275
|
173
173
|
meerschaum/connectors/plugin/PluginConnector.py,sha256=aQ1QaB7MordCFimZqoGLb0R12PfDUN_nWks2J5mzeAs,2084
|
174
174
|
meerschaum/connectors/plugin/__init__.py,sha256=pwF7TGY4WNz2_HaVdmK4rPQ9ZwTOEuPHgzOqsGcoXJw,198
|
175
|
-
meerschaum/connectors/sql/_SQLConnector.py,sha256=
|
175
|
+
meerschaum/connectors/sql/_SQLConnector.py,sha256=JVTK2LdUAtgK_fg0zgHOxgJHw7X7s0SHOunBZ9b-ai8,12084
|
176
176
|
meerschaum/connectors/sql/__init__.py,sha256=3cqYiDkVasn7zWdtOTAZbT4bo95AuvGOmDD2TkaAxtw,205
|
177
|
-
meerschaum/connectors/sql/_cli.py,sha256=
|
178
|
-
meerschaum/connectors/sql/_create_engine.py,sha256=
|
177
|
+
meerschaum/connectors/sql/_cli.py,sha256=3wXRfPSr5mXlM6Wt8UqrBYfWvkLVZ4jTzKRUd04enCo,5116
|
178
|
+
meerschaum/connectors/sql/_create_engine.py,sha256=h7c1nwdDWi33PBkRioPomHRT8h1DLc08EQ7INWyC_1Q,10717
|
179
179
|
meerschaum/connectors/sql/_fetch.py,sha256=mVe5zQo7SM9PSUU3Vjhacg4Bq1-Vttb7KkXL4p5YQdQ,12818
|
180
180
|
meerschaum/connectors/sql/_instance.py,sha256=xCc8M0xWMzF5Tu_1uWIFivAoHey5N1ccFhN_Z7u04zk,6304
|
181
181
|
meerschaum/connectors/sql/_pipes.py,sha256=8pp10lOYX8oVEqKHB9907Jny4nkT9fTgF8PrvhsdohI,128855
|
182
182
|
meerschaum/connectors/sql/_plugins.py,sha256=OVEdZ_UHTi-x5sF-5lu2TmR9ONxddp6SwDOmFo5TpU8,8051
|
183
183
|
meerschaum/connectors/sql/_sql.py,sha256=3hrANOId2DAoXsl8nvePnxvoXo5rtB5UfQsJK_fCY9s,42696
|
184
184
|
meerschaum/connectors/sql/_uri.py,sha256=BFzu5pjlbL3kxLH13vHWlpKGYTPfg8wuA2j58O9NsCM,3440
|
185
|
-
meerschaum/connectors/sql/_users.py,sha256=
|
185
|
+
meerschaum/connectors/sql/_users.py,sha256=mRyjsUCfPV52nfTQUbpu9gMXfV_DHXNqEhw4N-lSS4Q,9954
|
186
186
|
meerschaum/connectors/sql/tools.py,sha256=jz8huOaRCwGlYdtGfAqAh7SoK8uydYBrasKQba9FT38,187
|
187
187
|
meerschaum/connectors/sql/tables/__init__.py,sha256=53EeJsvmGjj68SpSShdt6kyLuk5Md5O8DnvWC1ra3u8,8876
|
188
188
|
meerschaum/connectors/sql/tables/types.py,sha256=Jc_MTHIBM-KHpQt__Lckp39CeOo7tGOiAk5faDx-znY,1573
|
@@ -209,29 +209,29 @@ meerschaum/core/Pipe/_index.py,sha256=cYgaVwBVfAYxJBZ6j6MXDqOxnOrD_QnYi33_kIwy_F
|
|
209
209
|
meerschaum/core/Pipe/_register.py,sha256=Sd5xaAW8H7uLTIoommcKb-6kHPRuHJLWNSbPnt2UbvA,2240
|
210
210
|
meerschaum/core/Pipe/_show.py,sha256=nG50y8eBT9TVuKkRgAKtNDNIxysJvMNxfu__lkL1F9k,1352
|
211
211
|
meerschaum/core/Pipe/_sync.py,sha256=NGiGhBI7M_nyIvVvyIA9_4jUKis1YpK4YL_pnceYGjg,38077
|
212
|
-
meerschaum/core/Pipe/_verify.py,sha256=
|
212
|
+
meerschaum/core/Pipe/_verify.py,sha256=aXRpD6azrN9A9Z3AXkKQw6NJFqNWqZVpgidjh5BsfLE,22565
|
213
213
|
meerschaum/core/Plugin/__init__.py,sha256=UXg64EvJPgI1PCxkY_KM02-ZmBm4FZpLPIQR_uSJJDc,137
|
214
214
|
meerschaum/core/User/_User.py,sha256=qbI0GIkr3G0PI4d9S49uatbJQ2kH_-z5-GoVJ0fuEtA,6624
|
215
215
|
meerschaum/core/User/__init__.py,sha256=8WkDRSBmxsprnKE7GB6j1yXSfEz9RinRkSzW0bzVP1I,870
|
216
216
|
meerschaum/jobs/_Executor.py,sha256=qM62BhFTM4tyJ7p90KOM0y3qyeRY9k3ZV_aTDJMHnO8,1682
|
217
217
|
meerschaum/jobs/_Job.py,sha256=D4TFrEQQ9EYqZrnepLBO7T3Sx2mOOdgBs2JnBdC1dNc,32257
|
218
218
|
meerschaum/jobs/__init__.py,sha256=YmZr1ZU8MLUjlTSLQ61Y6eE-a-SYuSMSMhiIpJKao_Y,12829
|
219
|
-
meerschaum/jobs/systemd.py,sha256=
|
219
|
+
meerschaum/jobs/systemd.py,sha256=CZbBkm-2z8z7G3CNmP5yBRj2VtWuxmxXVIv97cGhZGc,24613
|
220
220
|
meerschaum/plugins/_Plugin.py,sha256=bIo4HX8TTWIcwIHROwMt4VK6OoEUhY_3Qc8q-2dp-ZA,33895
|
221
221
|
meerschaum/plugins/__init__.py,sha256=Kl7Dz0CwUUxyjRC5RWnYo6WMLsOvdX2eQ38Rh3BjdzY,26465
|
222
222
|
meerschaum/plugins/bootstrap.py,sha256=VwjpZAuYdqPJW0YoVgAoM_taHkdQHqP902-8T7OWWCI,11339
|
223
223
|
meerschaum/utils/__init__.py,sha256=QrK1K9hIbPCRCM5k2nZGFqGnrqhA0Eh-iSmCU7FG6Cs,612
|
224
224
|
meerschaum/utils/_get_pipes.py,sha256=tu4xKPoDn79Dz2kWM13cXTP4DSCkn-3G9M8KiLftopw,11073
|
225
|
-
meerschaum/utils/dataframe.py,sha256=
|
225
|
+
meerschaum/utils/dataframe.py,sha256=f9h3fmG_ePHHls2NQmGHNqUurUEZBBvpS1UR7tQgwjI,49341
|
226
226
|
meerschaum/utils/debug.py,sha256=GyIzJmunkoPnOcZNYVQdT4Sgd-aOb5MI2VbIgATOjIQ,3695
|
227
227
|
meerschaum/utils/interactive.py,sha256=t-6jWozXSqL7lYGDHuwiOjTgr-UKhdcg61q_eR5mikI,3196
|
228
228
|
meerschaum/utils/misc.py,sha256=8TOQQlFyF_aYnc8tnx98lccXr9tFrdlS-ngXeOQjHHY,47407
|
229
229
|
meerschaum/utils/networking.py,sha256=Sr_eYUGW8_UV9-k9LqRFf7xLtbUcsDucODyLCRsFRUc,1006
|
230
230
|
meerschaum/utils/pool.py,sha256=vkE42af4fjrTEJTxf6Ek3xGucm1MtEkpsSEiaVzNKHs,2655
|
231
|
-
meerschaum/utils/process.py,sha256=
|
231
|
+
meerschaum/utils/process.py,sha256=as0-CjG4mqFP0TydVvmAmgki6er4thS5BqUopeiq98Q,8216
|
232
232
|
meerschaum/utils/prompt.py,sha256=qj1As1tuiL0GZTku_YOC6I5DmOU6L5otDR7DW7LA5fM,19397
|
233
|
-
meerschaum/utils/schedule.py,sha256=
|
234
|
-
meerschaum/utils/sql.py,sha256=
|
233
|
+
meerschaum/utils/schedule.py,sha256=Vrcd2Qs-UPVn6xBayNUIgludf0Mlb6Wrgq6ATdyhV8c,11451
|
234
|
+
meerschaum/utils/sql.py,sha256=2p8pa3kBCE5lM6tDle5HV4AamZCgOpnKmCB6mdkiLUA,80287
|
235
235
|
meerschaum/utils/threading.py,sha256=awjbVL_QR6G-o_9Qk85utac9cSdqkiC8tQSdERCdrG8,2814
|
236
236
|
meerschaum/utils/typing.py,sha256=U3MC347sh1umpa3Xr1k71eADyDmk4LB6TnVCpq8dVzI,2830
|
237
237
|
meerschaum/utils/warnings.py,sha256=n-phr3BftNNgyPnvnXC_VMSjtCvjiCZ-ewmVfcROhkc,6611
|
@@ -250,15 +250,15 @@ meerschaum/utils/formatting/_pipes.py,sha256=gwl8-xCN5GYqBZJ7SkY20BebcofY0nU5X8Y
|
|
250
250
|
meerschaum/utils/formatting/_pprint.py,sha256=wyTmjHFnsHbxfyuytjTWzH-D42Z65GuIisQ_W6UnRPg,3096
|
251
251
|
meerschaum/utils/formatting/_shell.py,sha256=XH7VFLteNv7NGtWhJl7FdIGt80sKeTiDoJokGSDAwBM,3761
|
252
252
|
meerschaum/utils/packages/__init__.py,sha256=TdKaj2tmN4bFwzusOfMv24P5ET7Zv73vyoOf9GOIr5E,64427
|
253
|
-
meerschaum/utils/packages/_packages.py,sha256=
|
253
|
+
meerschaum/utils/packages/_packages.py,sha256=yeeMIUWr7TkMknGmkzUj4_BJtidOoCadW7m0C389_UQ,8868
|
254
254
|
meerschaum/utils/packages/lazy_loader.py,sha256=VHnph3VozH29R4JnSSBfwtA5WKZYZQFT_GeQSShCnuc,2540
|
255
255
|
meerschaum/utils/venv/_Venv.py,sha256=gc1TCeAj-kTZbQFAT9xl1bi4HXFV5ApT0dPOJfxwr78,3748
|
256
|
-
meerschaum/utils/venv/__init__.py,sha256
|
257
|
-
meerschaum-2.8.
|
258
|
-
meerschaum-2.8.
|
259
|
-
meerschaum-2.8.
|
260
|
-
meerschaum-2.8.
|
261
|
-
meerschaum-2.8.
|
262
|
-
meerschaum-2.8.
|
263
|
-
meerschaum-2.8.
|
264
|
-
meerschaum-2.8.
|
256
|
+
meerschaum/utils/venv/__init__.py,sha256=AJH9BEO2Eadwn17E_uynca_picaJTlMPP_s4y5RHpJw,27187
|
257
|
+
meerschaum-2.8.4.dist-info/LICENSE,sha256=jG2zQEdRNt88EgHUWPpXVWmOrOduUQRx7MnYV9YIPaw,11359
|
258
|
+
meerschaum-2.8.4.dist-info/METADATA,sha256=ADfvDN1hru7HrOqr5MwrRFd0qLB9Y2ewvoa3H0nE9Ss,24489
|
259
|
+
meerschaum-2.8.4.dist-info/NOTICE,sha256=OTA9Fcthjf5BRvWDDIcBC_xfLpeDV-RPZh3M-HQBRtQ,114
|
260
|
+
meerschaum-2.8.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
261
|
+
meerschaum-2.8.4.dist-info/entry_points.txt,sha256=5YBVzibw-0rNA_1VjB16z5GABsOGf-CDhW4yqH8C7Gc,88
|
262
|
+
meerschaum-2.8.4.dist-info/top_level.txt,sha256=bNoSiDj0El6buocix-FRoAtJOeq1qOF5rRm2u9i7Q6A,11
|
263
|
+
meerschaum-2.8.4.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
264
|
+
meerschaum-2.8.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|