meerschaum 2.6.17__py3-none-any.whl → 2.7.0rc1__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/actions/delete.py +65 -69
- meerschaum/actions/install.py +1 -2
- meerschaum/config/_default.py +1 -1
- meerschaum/config/_paths.py +2 -1
- meerschaum/config/_version.py +1 -1
- meerschaum/connectors/api/_pipes.py +4 -3
- meerschaum/connectors/sql/_pipes.py +63 -25
- meerschaum/connectors/sql/_sql.py +6 -1
- meerschaum/connectors/valkey/_pipes.py +12 -1
- meerschaum/core/Pipe/__init__.py +23 -13
- meerschaum/core/Pipe/_attributes.py +19 -0
- meerschaum/core/Pipe/_dtypes.py +1 -1
- meerschaum/core/Pipe/_sync.py +61 -21
- meerschaum/core/Pipe/_verify.py +8 -7
- meerschaum/plugins/_Plugin.py +11 -14
- meerschaum/utils/daemon/Daemon.py +18 -11
- meerschaum/utils/dataframe.py +175 -13
- meerschaum/utils/dtypes/__init__.py +103 -14
- meerschaum/utils/dtypes/sql.py +26 -0
- meerschaum/utils/misc.py +8 -8
- meerschaum/utils/sql.py +64 -11
- meerschaum/utils/venv/_Venv.py +4 -4
- meerschaum/utils/venv/__init__.py +33 -13
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/METADATA +1 -1
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/RECORD +31 -31
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/LICENSE +0 -0
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/NOTICE +0 -0
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/WHEEL +0 -0
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.6.17.dist-info → meerschaum-2.7.0rc1.dist-info}/zip-safe +0 -0
meerschaum/actions/delete.py
CHANGED
@@ -9,6 +9,7 @@ Functions for deleting elements.
|
|
9
9
|
from __future__ import annotations
|
10
10
|
from meerschaum.utils.typing import Any, SuccessTuple, Union, Optional, List
|
11
11
|
|
12
|
+
|
12
13
|
def delete(
|
13
14
|
action: Optional[List[str]] = None,
|
14
15
|
**kw: Any
|
@@ -21,7 +22,6 @@ def delete(
|
|
21
22
|
|
22
23
|
"""
|
23
24
|
from meerschaum.actions import choose_subaction
|
24
|
-
from meerschaum.utils.debug import dprint
|
25
25
|
options = {
|
26
26
|
'config' : _delete_config,
|
27
27
|
'pipes' : _delete_pipes,
|
@@ -65,19 +65,18 @@ def _complete_delete(
|
|
65
65
|
|
66
66
|
|
67
67
|
def _delete_pipes(
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
debug: bool = False,
|
69
|
+
yes: bool = False,
|
70
|
+
force: bool = False,
|
71
|
+
noask: bool = False,
|
72
|
+
**kw: Any
|
73
|
+
) -> SuccessTuple:
|
74
74
|
"""
|
75
75
|
Drop pipes and delete their registrations.
|
76
|
-
|
77
76
|
"""
|
78
77
|
from meerschaum import get_pipes
|
79
78
|
from meerschaum.utils.prompt import yes_no
|
80
|
-
from meerschaum.utils.formatting import
|
79
|
+
from meerschaum.utils.formatting import highlight_pipes
|
81
80
|
from meerschaum.utils.warnings import warn
|
82
81
|
from meerschaum.actions import actions
|
83
82
|
pipes = get_pipes(as_list=True, debug=debug, **kw)
|
@@ -126,21 +125,22 @@ def _delete_pipes(
|
|
126
125
|
|
127
126
|
return successes > 0, msg
|
128
127
|
|
128
|
+
|
129
129
|
def _delete_config(
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
130
|
+
action: Optional[List[str]] = None,
|
131
|
+
yes: bool = False,
|
132
|
+
force: bool = False,
|
133
|
+
noask: bool = False,
|
134
|
+
debug: bool = False,
|
135
|
+
**kw: Any
|
136
|
+
) -> SuccessTuple:
|
137
137
|
"""
|
138
138
|
Delete configuration files.
|
139
|
-
|
140
139
|
"""
|
141
|
-
import os
|
140
|
+
import os
|
141
|
+
import shutil
|
142
142
|
from meerschaum.utils.prompt import yes_no
|
143
|
-
from meerschaum.config._paths import
|
143
|
+
from meerschaum.config._paths import STACK_COMPOSE_PATH, DEFAULT_CONFIG_DIR_PATH
|
144
144
|
from meerschaum.config._read_config import get_possible_keys, get_keyfile_path
|
145
145
|
from meerschaum.utils.debug import dprint
|
146
146
|
paths = [p for p in [STACK_COMPOSE_PATH, DEFAULT_CONFIG_DIR_PATH] if p.exists()]
|
@@ -157,7 +157,7 @@ def _delete_config(
|
|
157
157
|
else:
|
158
158
|
sep = '\n' + ' - '
|
159
159
|
answer = yes_no(
|
160
|
-
|
160
|
+
"Are you sure you want to delete the following configuration files?" +
|
161
161
|
f"{sep + sep.join([str(p) for p in paths])}\n",
|
162
162
|
default='n', noask=noask, yes=yes
|
163
163
|
)
|
@@ -176,18 +176,18 @@ def _delete_config(
|
|
176
176
|
|
177
177
|
return success, msg
|
178
178
|
|
179
|
+
|
179
180
|
def _delete_plugins(
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
181
|
+
action: Optional[List[str]] = None,
|
182
|
+
repository: Optional[str] = None,
|
183
|
+
yes: bool = False,
|
184
|
+
force: bool = False,
|
185
|
+
noask: bool = False,
|
186
|
+
debug: bool = False,
|
187
|
+
**kw: Any
|
188
|
+
) -> SuccessTuple:
|
188
189
|
"""
|
189
190
|
Delete plugins from a Meerschaum repository.
|
190
|
-
|
191
191
|
"""
|
192
192
|
from meerschaum.utils.warnings import info
|
193
193
|
from meerschaum.plugins import reload_plugins
|
@@ -206,7 +206,7 @@ def _delete_plugins(
|
|
206
206
|
) if not force else True
|
207
207
|
|
208
208
|
if not answer:
|
209
|
-
return False,
|
209
|
+
return False, "No plugins deleted."
|
210
210
|
|
211
211
|
successes = {}
|
212
212
|
for name in action:
|
@@ -218,27 +218,24 @@ def _delete_plugins(
|
|
218
218
|
reload_plugins(debug=debug)
|
219
219
|
return True, "Success"
|
220
220
|
|
221
|
+
|
221
222
|
def _delete_users(
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
223
|
+
action: Optional[List[str]] = None,
|
224
|
+
mrsm_instance: Optional[str] = None,
|
225
|
+
yes: bool = False,
|
226
|
+
force: bool = False,
|
227
|
+
noask: bool = False,
|
228
|
+
shell: bool = False,
|
229
|
+
debug: bool = False,
|
230
|
+
**kw
|
231
|
+
) -> SuccessTuple:
|
231
232
|
"""
|
232
233
|
Delete users from a Meerschaum instance. Adequate permissions are required.
|
233
|
-
|
234
234
|
"""
|
235
|
-
from meerschaum import get_connector
|
236
235
|
from meerschaum.connectors.parse import parse_instance_keys
|
237
|
-
from meerschaum.utils.prompt import yes_no
|
238
|
-
from meerschaum.utils.
|
239
|
-
from meerschaum.utils.warnings import warn, error, info
|
236
|
+
from meerschaum.utils.prompt import yes_no
|
237
|
+
from meerschaum.utils.warnings import info
|
240
238
|
from meerschaum.core import User
|
241
|
-
from meerschaum.connectors.api import APIConnector
|
242
239
|
from meerschaum.utils.formatting import print_tuple
|
243
240
|
instance_connector = parse_instance_keys(mrsm_instance)
|
244
241
|
|
@@ -292,24 +289,25 @@ def _delete_users(
|
|
292
289
|
)
|
293
290
|
return True, msg
|
294
291
|
|
292
|
+
|
295
293
|
def _delete_connectors(
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
294
|
+
action: Optional[List[str]] = None,
|
295
|
+
connector_keys: Optional[List[str]] = None,
|
296
|
+
yes: bool = False,
|
297
|
+
force: bool = False,
|
298
|
+
noask: bool = False,
|
299
|
+
debug: bool = False,
|
300
|
+
**kw: Any
|
301
|
+
) -> SuccessTuple:
|
304
302
|
"""
|
305
303
|
Delete configured connectors.
|
306
304
|
|
307
305
|
Example:
|
308
306
|
`delete connectors sql:test`
|
309
|
-
|
310
307
|
"""
|
311
|
-
import os
|
312
|
-
|
308
|
+
import os
|
309
|
+
import pathlib
|
310
|
+
from meerschaum.utils.prompt import yes_no
|
313
311
|
from meerschaum.connectors.parse import parse_connector_keys
|
314
312
|
from meerschaum.config import _config
|
315
313
|
from meerschaum.config._edit import write_config
|
@@ -329,7 +327,7 @@ def _delete_connectors(
|
|
329
327
|
for ck in _keys:
|
330
328
|
try:
|
331
329
|
conn = parse_connector_keys(ck, debug=debug)
|
332
|
-
except Exception
|
330
|
+
except Exception:
|
333
331
|
warn(f"Could not parse connector '{ck}'. Skipping...", stack=False)
|
334
332
|
continue
|
335
333
|
|
@@ -357,26 +355,27 @@ def _delete_connectors(
|
|
357
355
|
):
|
358
356
|
try:
|
359
357
|
os.remove(c.database)
|
360
|
-
except Exception
|
358
|
+
except Exception:
|
361
359
|
warn(
|
362
360
|
"Failed to delete database file for connector "
|
363
361
|
+ f"'{c}'. Ignoring...", stack=False
|
364
362
|
)
|
365
|
-
except Exception
|
363
|
+
except Exception:
|
366
364
|
pass
|
367
365
|
try:
|
368
366
|
del cf['meerschaum']['connectors'][c.type][c.label]
|
369
|
-
except Exception
|
367
|
+
except Exception:
|
370
368
|
warn(f"Failed to delete connector '{c}' from configuration. Skipping...", stack=False)
|
371
369
|
|
372
370
|
write_config(cf, debug=debug)
|
373
371
|
return True, "Success"
|
374
372
|
|
373
|
+
|
375
374
|
def _complete_delete_connectors(
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
375
|
+
action: Optional[List[str]] = None,
|
376
|
+
line: str = '',
|
377
|
+
**kw: Any
|
378
|
+
) -> List[str]:
|
380
379
|
from meerschaum.config import get_config
|
381
380
|
from meerschaum.utils.misc import get_connector_labels
|
382
381
|
types = list(get_config('meerschaum', 'connectors').keys())
|
@@ -401,10 +400,8 @@ def _delete_jobs(
|
|
401
400
|
Remove a job's log files and delete the job's ID.
|
402
401
|
|
403
402
|
If the job is running, ask to kill the job first.
|
404
|
-
|
405
403
|
"""
|
406
404
|
from meerschaum.jobs import (
|
407
|
-
Job,
|
408
405
|
get_running_jobs,
|
409
406
|
get_stopped_jobs,
|
410
407
|
get_filtered_jobs,
|
@@ -460,7 +457,7 @@ def _delete_jobs(
|
|
460
457
|
### Ensure the running jobs are dead.
|
461
458
|
if get_running_jobs(executor_keys, jobs, debug=debug):
|
462
459
|
return False, (
|
463
|
-
|
460
|
+
"Failed to kill running jobs. Please stop these jobs before deleting."
|
464
461
|
)
|
465
462
|
_to_delete.update(to_stop_jobs)
|
466
463
|
|
@@ -475,7 +472,7 @@ def _delete_jobs(
|
|
475
472
|
pprint_jobs(_to_delete, nopretty=nopretty)
|
476
473
|
if not yes_no(
|
477
474
|
"Are you sure you want to delete these jobs?",
|
478
|
-
yes=yes, noask=noask, default='
|
475
|
+
yes=yes, noask=noask, default='n',
|
479
476
|
):
|
480
477
|
return False, "No jobs were deleted."
|
481
478
|
|
@@ -569,7 +566,6 @@ def _delete_venvs(
|
|
569
566
|
from meerschaum.utils.venv import venv_exists
|
570
567
|
from meerschaum.utils.prompt import yes_no
|
571
568
|
from meerschaum.utils.misc import print_options
|
572
|
-
from meerschaum.utils.warnings import warn
|
573
569
|
|
574
570
|
venvs_to_skip = ['mrsm']
|
575
571
|
venvs = [
|
meerschaum/actions/install.py
CHANGED
@@ -175,7 +175,7 @@ def _install_packages(
|
|
175
175
|
+ f" into the virtual environment '{venv}'."
|
176
176
|
)
|
177
177
|
return False, (
|
178
|
-
|
178
|
+
"Failed to install package" + ("s" if len(action) != 1 else '') + f" {items_str(action)}."
|
179
179
|
)
|
180
180
|
|
181
181
|
|
@@ -200,7 +200,6 @@ def _install_required(
|
|
200
200
|
from meerschaum.core import Plugin
|
201
201
|
from meerschaum.utils.warnings import warn, info
|
202
202
|
from meerschaum.connectors.parse import parse_repo_keys
|
203
|
-
from meerschaum.utils.formatting import print_tuple
|
204
203
|
from meerschaum.plugins import get_plugins_names
|
205
204
|
repo_connector = parse_repo_keys(repository)
|
206
205
|
|
meerschaum/config/_default.py
CHANGED
meerschaum/config/_paths.py
CHANGED
@@ -103,7 +103,7 @@ if ENVIRONMENT_VENVS_DIR in os.environ:
|
|
103
103
|
if not _VENVS_DIR_PATH.exists():
|
104
104
|
try:
|
105
105
|
_VENVS_DIR_PATH.mkdir(parents=True, exist_ok=True)
|
106
|
-
except Exception
|
106
|
+
except Exception:
|
107
107
|
print(
|
108
108
|
f"Invalid path set for environment variable '{ENVIRONMENT_VENVS_DIR}':\n"
|
109
109
|
+ f"{_VENVS_DIR_PATH}"
|
@@ -148,6 +148,7 @@ paths = {
|
|
148
148
|
'CACHE_RESOURCES_PATH' : ('{ROOT_DIR_PATH}', '.cache'),
|
149
149
|
'PIPES_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'pipes'),
|
150
150
|
'USERS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'users'),
|
151
|
+
'VENVS_CACHE_RESOURCES_PATH' : ('{CACHE_RESOURCES_PATH}', 'venvs'),
|
151
152
|
|
152
153
|
'PLUGINS_RESOURCES_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins'),
|
153
154
|
'PLUGINS_INTERNAL_LOCK_PATH' : ('{INTERNAL_RESOURCES_PATH}', 'plugins.lock'),
|
meerschaum/config/_version.py
CHANGED
@@ -15,7 +15,8 @@ from datetime import datetime
|
|
15
15
|
import meerschaum as mrsm
|
16
16
|
from meerschaum.utils.debug import dprint
|
17
17
|
from meerschaum.utils.warnings import warn, error
|
18
|
-
from meerschaum.utils.typing import SuccessTuple, Union, Any, Optional,
|
18
|
+
from meerschaum.utils.typing import SuccessTuple, Union, Any, Optional, List, Dict, Tuple
|
19
|
+
|
19
20
|
|
20
21
|
def pipe_r_url(
|
21
22
|
pipe: mrsm.Pipe
|
@@ -30,6 +31,7 @@ def pipe_r_url(
|
|
30
31
|
+ f"{pipe.connector_keys}/{pipe.metric_key}/{location_key}"
|
31
32
|
)
|
32
33
|
|
34
|
+
|
33
35
|
def register_pipe(
|
34
36
|
self,
|
35
37
|
pipe: mrsm.Pipe,
|
@@ -39,7 +41,6 @@ def register_pipe(
|
|
39
41
|
Returns a tuple of (success_bool, response_dict).
|
40
42
|
"""
|
41
43
|
from meerschaum.utils.debug import dprint
|
42
|
-
from meerschaum.config.static import STATIC_CONFIG
|
43
44
|
### NOTE: if `parameters` is supplied in the Pipe constructor,
|
44
45
|
### then `pipe.parameters` will exist and not be fetched from the database.
|
45
46
|
r_url = pipe_r_url(pipe)
|
@@ -180,7 +181,7 @@ def sync_pipe(
|
|
180
181
|
from meerschaum.utils.misc import json_serialize_datetime, items_str
|
181
182
|
from meerschaum.config import get_config
|
182
183
|
from meerschaum.utils.packages import attempt_import
|
183
|
-
from meerschaum.utils.dataframe import get_numeric_cols, to_json
|
184
|
+
from meerschaum.utils.dataframe import get_numeric_cols, to_json, get_bytes_cols
|
184
185
|
begin = time.time()
|
185
186
|
more_itertools = attempt_import('more_itertools')
|
186
187
|
if df is None:
|
@@ -460,10 +460,16 @@ def get_create_index_queries(
|
|
460
460
|
else None
|
461
461
|
)
|
462
462
|
primary_key_constraint_name = (
|
463
|
-
sql_item_name(f'
|
463
|
+
sql_item_name(f'PK_{pipe.target}', self.flavor, None)
|
464
464
|
if primary_key is not None
|
465
465
|
else None
|
466
466
|
)
|
467
|
+
primary_key_clustered = "CLUSTERED" if _datetime is None else "NONCLUSTERED"
|
468
|
+
datetime_clustered = (
|
469
|
+
"CLUSTERED"
|
470
|
+
if not existing_primary_keys and _datetime is not None
|
471
|
+
else "NONCLUSTERED"
|
472
|
+
)
|
467
473
|
|
468
474
|
_id_index_name = (
|
469
475
|
sql_item_name(index_names['id'], self.flavor, None)
|
@@ -474,6 +480,7 @@ def get_create_index_queries(
|
|
474
480
|
_create_space_partition = get_config('system', 'experimental', 'space')
|
475
481
|
|
476
482
|
### create datetime index
|
483
|
+
dt_query = None
|
477
484
|
if _datetime is not None:
|
478
485
|
if self.flavor == 'timescaledb' and pipe.parameters.get('hypertable', True):
|
479
486
|
_id_count = (
|
@@ -504,19 +511,19 @@ def get_create_index_queries(
|
|
504
511
|
+ 'if_not_exists => true, '
|
505
512
|
+ "migrate_data => true);"
|
506
513
|
)
|
507
|
-
elif
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
)
|
514
|
+
elif _datetime_index_name:
|
515
|
+
if self.flavor == 'mssql':
|
516
|
+
dt_query = (
|
517
|
+
f"CREATE {datetime_clustered} INDEX {_datetime_index_name} "
|
518
|
+
f"ON {_pipe_name} ({_datetime_name})"
|
519
|
+
)
|
520
|
+
else:
|
521
|
+
dt_query = (
|
522
|
+
f"CREATE INDEX {_datetime_index_name} "
|
523
|
+
+ f"ON {_pipe_name} ({_datetime_name})"
|
524
|
+
)
|
519
525
|
|
526
|
+
if dt_query:
|
520
527
|
index_queries[_datetime] = [dt_query]
|
521
528
|
|
522
529
|
primary_queries = []
|
@@ -623,7 +630,7 @@ def get_create_index_queries(
|
|
623
630
|
),
|
624
631
|
(
|
625
632
|
f"ALTER TABLE {_pipe_name}\n"
|
626
|
-
f"ADD CONSTRAINT {primary_key_constraint_name} PRIMARY KEY ({primary_key_name})"
|
633
|
+
f"ADD CONSTRAINT {primary_key_constraint_name} PRIMARY KEY {primary_key_clustered} ({primary_key_name})"
|
627
634
|
),
|
628
635
|
])
|
629
636
|
index_queries[primary_key] = primary_queries
|
@@ -875,6 +882,7 @@ def get_pipe_data(
|
|
875
882
|
from meerschaum.utils.dtypes import (
|
876
883
|
attempt_cast_to_numeric,
|
877
884
|
attempt_cast_to_uuid,
|
885
|
+
attempt_cast_to_bytes,
|
878
886
|
are_dtypes_equal,
|
879
887
|
)
|
880
888
|
from meerschaum.utils.dtypes.sql import get_pd_type_from_db_type
|
@@ -891,17 +899,15 @@ def get_pipe_data(
|
|
891
899
|
col: get_pd_type_from_db_type(typ)
|
892
900
|
for col, typ in cols_types.items()
|
893
901
|
}
|
894
|
-
}
|
902
|
+
} if pipe.enforce else {}
|
895
903
|
if dtypes:
|
896
904
|
if self.flavor == 'sqlite':
|
897
905
|
if not pipe.columns.get('datetime', None):
|
898
906
|
_dt = pipe.guess_datetime()
|
899
907
|
dt = sql_item_name(_dt, self.flavor, None) if _dt else None
|
900
|
-
is_guess = True
|
901
908
|
else:
|
902
909
|
_dt = pipe.get_columns('datetime')
|
903
910
|
dt = sql_item_name(_dt, self.flavor, None)
|
904
|
-
is_guess = False
|
905
911
|
|
906
912
|
if _dt:
|
907
913
|
dt_type = dtypes.get(_dt, 'object').lower()
|
@@ -929,7 +935,7 @@ def get_pipe_data(
|
|
929
935
|
col: to_pandas_dtype(typ)
|
930
936
|
for col, typ in dtypes.items()
|
931
937
|
if col in select_columns and col not in (omit_columns or [])
|
932
|
-
}
|
938
|
+
} if pipe.enforce else {}
|
933
939
|
query = self.get_pipe_data_query(
|
934
940
|
pipe,
|
935
941
|
select_columns=select_columns,
|
@@ -959,6 +965,11 @@ def get_pipe_data(
|
|
959
965
|
for col, typ in pipe.dtypes.items()
|
960
966
|
if typ == 'uuid' and col in dtypes
|
961
967
|
]
|
968
|
+
bytes_columns = [
|
969
|
+
col
|
970
|
+
for col, typ in pipe.dtypes.items()
|
971
|
+
if typ == 'bytes' and col in dtypes
|
972
|
+
]
|
962
973
|
|
963
974
|
kw['coerce_float'] = kw.get('coerce_float', (len(numeric_columns) == 0))
|
964
975
|
|
@@ -978,6 +989,11 @@ def get_pipe_data(
|
|
978
989
|
continue
|
979
990
|
df[col] = df[col].apply(attempt_cast_to_uuid)
|
980
991
|
|
992
|
+
for col in bytes_columns:
|
993
|
+
if col not in df.columns:
|
994
|
+
continue
|
995
|
+
df[col] = df[col].apply(attempt_cast_to_bytes)
|
996
|
+
|
981
997
|
if self.flavor == 'sqlite':
|
982
998
|
ignore_dt_cols = [
|
983
999
|
col
|
@@ -1339,7 +1355,13 @@ def create_pipe_table_from_df(
|
|
1339
1355
|
"""
|
1340
1356
|
Create a pipe's table from its configured dtypes and an incoming dataframe.
|
1341
1357
|
"""
|
1342
|
-
from meerschaum.utils.dataframe import
|
1358
|
+
from meerschaum.utils.dataframe import (
|
1359
|
+
get_json_cols,
|
1360
|
+
get_numeric_cols,
|
1361
|
+
get_uuid_cols,
|
1362
|
+
get_datetime_cols,
|
1363
|
+
get_bytes_cols,
|
1364
|
+
)
|
1343
1365
|
from meerschaum.utils.sql import get_create_table_queries, sql_item_name
|
1344
1366
|
primary_key = pipe.columns.get('primary', None)
|
1345
1367
|
dt_col = pipe.columns.get('datetime', None)
|
@@ -1365,6 +1387,18 @@ def create_pipe_table_from_df(
|
|
1365
1387
|
col: 'numeric'
|
1366
1388
|
for col in get_numeric_cols(df)
|
1367
1389
|
},
|
1390
|
+
**{
|
1391
|
+
col: 'bytes'
|
1392
|
+
for col in get_bytes_cols(df)
|
1393
|
+
},
|
1394
|
+
**{
|
1395
|
+
col: 'datetime64[ns, UTC]'
|
1396
|
+
for col in get_datetime_cols(df, timezone_aware=True, timezone_naive=False)
|
1397
|
+
},
|
1398
|
+
**{
|
1399
|
+
col: 'datetime64[ns]'
|
1400
|
+
for col in get_datetime_cols(df, timezone_aware=False, timezone_naive=True)
|
1401
|
+
},
|
1368
1402
|
**pipe.dtypes
|
1369
1403
|
}
|
1370
1404
|
autoincrement = (
|
@@ -1455,11 +1489,9 @@ def sync_pipe(
|
|
1455
1489
|
get_update_queries,
|
1456
1490
|
sql_item_name,
|
1457
1491
|
update_queries,
|
1458
|
-
get_create_table_queries,
|
1459
1492
|
get_reset_autoincrement_queries,
|
1460
1493
|
)
|
1461
1494
|
from meerschaum.utils.misc import generate_password
|
1462
|
-
from meerschaum.utils.dataframe import get_json_cols, get_numeric_cols, get_uuid_cols
|
1463
1495
|
from meerschaum.utils.dtypes import are_dtypes_equal
|
1464
1496
|
from meerschaum.utils.dtypes.sql import get_db_type_from_pd_type
|
1465
1497
|
from meerschaum import Pipe
|
@@ -1572,6 +1604,7 @@ def sync_pipe(
|
|
1572
1604
|
'schema': self.get_pipe_schema(pipe),
|
1573
1605
|
})
|
1574
1606
|
|
1607
|
+
dt_col = pipe.columns.get('datetime', None)
|
1575
1608
|
primary_key = pipe.columns.get('primary', None)
|
1576
1609
|
autoincrement = (
|
1577
1610
|
pipe.parameters.get('autoincrement', False)
|
@@ -1714,7 +1747,11 @@ def sync_pipe(
|
|
1714
1747
|
col
|
1715
1748
|
for col_key, col in pipe.columns.items()
|
1716
1749
|
if col and col in existing_cols
|
1717
|
-
]
|
1750
|
+
] if not primary_key else (
|
1751
|
+
[dt_col, primary_key]
|
1752
|
+
if self.flavor == 'timescaledb' and dt_col and dt_col in update_df.columns
|
1753
|
+
else [primary_key]
|
1754
|
+
)
|
1718
1755
|
update_queries = get_update_queries(
|
1719
1756
|
pipe.target,
|
1720
1757
|
temp_target,
|
@@ -1723,7 +1760,8 @@ def sync_pipe(
|
|
1723
1760
|
upsert=upsert,
|
1724
1761
|
schema=self.get_pipe_schema(pipe),
|
1725
1762
|
patch_schema=self.internal_schema,
|
1726
|
-
datetime_col=
|
1763
|
+
datetime_col=(dt_col if dt_col in update_df.columns else None),
|
1764
|
+
identity_insert=(autoincrement and primary_key in update_df.columns),
|
1727
1765
|
debug=debug,
|
1728
1766
|
)
|
1729
1767
|
update_success = all(
|
@@ -1841,7 +1879,6 @@ def sync_pipe_inplace(
|
|
1841
1879
|
session_execute,
|
1842
1880
|
update_queries,
|
1843
1881
|
)
|
1844
|
-
from meerschaum.utils.dtypes import are_dtypes_equal
|
1845
1882
|
from meerschaum.utils.dtypes.sql import (
|
1846
1883
|
get_pd_type_from_db_type,
|
1847
1884
|
)
|
@@ -2061,6 +2098,7 @@ def sync_pipe_inplace(
|
|
2061
2098
|
) if not (upsert or static) else new_cols_types
|
2062
2099
|
|
2063
2100
|
common_cols = [col for col in new_cols if col in backtrack_cols_types]
|
2101
|
+
primary_key = pipe.columns.get('primary', None)
|
2064
2102
|
on_cols = {
|
2065
2103
|
col: new_cols.get(col)
|
2066
2104
|
for col_key, col in pipe.columns.items()
|
@@ -2071,7 +2109,7 @@ def sync_pipe_inplace(
|
|
2071
2109
|
and col in backtrack_cols_types
|
2072
2110
|
and col in new_cols
|
2073
2111
|
)
|
2074
|
-
}
|
2112
|
+
} if not primary_key else {primary_key: new_cols.get(primary_key)}
|
2075
2113
|
|
2076
2114
|
null_replace_new_cols_str = (
|
2077
2115
|
', '.join([
|
@@ -790,7 +790,12 @@ def to_sql(
|
|
790
790
|
truncate_item_name,
|
791
791
|
DROP_IF_EXISTS_FLAVORS,
|
792
792
|
)
|
793
|
-
from meerschaum.utils.dataframe import
|
793
|
+
from meerschaum.utils.dataframe import (
|
794
|
+
get_json_cols,
|
795
|
+
get_numeric_cols,
|
796
|
+
get_uuid_cols,
|
797
|
+
get_bytes_cols,
|
798
|
+
)
|
794
799
|
from meerschaum.utils.dtypes import are_dtypes_equal, quantize_decimal, coerce_timezone
|
795
800
|
from meerschaum.utils.dtypes.sql import (
|
796
801
|
NUMERIC_PRECISION_FLAVORS,
|
@@ -46,9 +46,20 @@ def serialize_document(doc: Dict[str, Any]) -> str:
|
|
46
46
|
-------
|
47
47
|
A serialized string for the document.
|
48
48
|
"""
|
49
|
+
from meerschaum.utils.dtypes import serialize_bytes
|
49
50
|
return json.dumps(
|
50
51
|
doc,
|
51
|
-
default=(
|
52
|
+
default=(
|
53
|
+
lambda x: (
|
54
|
+
json_serialize_datetime(x)
|
55
|
+
if hasattr(x, 'tzinfo')
|
56
|
+
else (
|
57
|
+
serialize_bytes(x)
|
58
|
+
if isinstance(x, bytes)
|
59
|
+
else str(x)
|
60
|
+
)
|
61
|
+
)
|
62
|
+
),
|
52
63
|
separators=(',', ':'),
|
53
64
|
sort_keys=True,
|
54
65
|
)
|