meerschaum 2.4.0.dev0__py3-none-any.whl → 2.4.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/_internal/arguments/_parse_arguments.py +2 -5
- meerschaum/_internal/docs/index.py +3 -2
- meerschaum/_internal/entry.py +13 -7
- meerschaum/_internal/shell/Shell.py +38 -44
- meerschaum/_internal/term/TermPageHandler.py +2 -3
- meerschaum/_internal/term/__init__.py +13 -11
- meerschaum/actions/api.py +10 -7
- meerschaum/actions/bootstrap.py +2 -1
- meerschaum/actions/copy.py +3 -3
- meerschaum/actions/delete.py +4 -1
- meerschaum/actions/register.py +1 -3
- meerschaum/actions/stack.py +24 -19
- meerschaum/actions/start.py +25 -26
- meerschaum/actions/sync.py +53 -52
- meerschaum/api/__init__.py +48 -14
- meerschaum/api/_events.py +15 -10
- meerschaum/api/_oauth2.py +2 -2
- meerschaum/api/_websockets.py +5 -4
- meerschaum/api/dash/__init__.py +1 -11
- meerschaum/api/dash/callbacks/dashboard.py +47 -55
- meerschaum/api/dash/callbacks/jobs.py +15 -16
- meerschaum/api/dash/callbacks/login.py +16 -10
- meerschaum/api/dash/callbacks/pipes.py +3 -4
- meerschaum/api/dash/callbacks/plugins.py +1 -1
- meerschaum/api/dash/callbacks/register.py +15 -11
- meerschaum/api/dash/components.py +54 -59
- meerschaum/api/dash/jobs.py +5 -9
- meerschaum/api/dash/pages/pipes.py +4 -1
- meerschaum/api/dash/pipes.py +13 -17
- meerschaum/api/dash/plugins.py +6 -4
- meerschaum/api/dash/sessions.py +176 -0
- meerschaum/api/dash/users.py +2 -53
- meerschaum/api/dash/webterm.py +12 -17
- meerschaum/api/resources/static/js/terminado.js +1 -1
- meerschaum/api/routes/_actions.py +4 -20
- meerschaum/api/routes/_jobs.py +8 -7
- meerschaum/api/routes/_webterm.py +5 -6
- meerschaum/config/_default.py +6 -1
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +9 -7
- meerschaum/config/static/__init__.py +4 -0
- meerschaum/connectors/__init__.py +15 -9
- meerschaum/connectors/api/{APIConnector.py → _APIConnector.py} +3 -1
- meerschaum/connectors/api/__init__.py +2 -1
- meerschaum/connectors/parse.py +18 -16
- meerschaum/connectors/sql/__init__.py +3 -1
- meerschaum/connectors/sql/_pipes.py +39 -39
- meerschaum/connectors/valkey/{ValkeyConnector.py → _ValkeyConnector.py} +5 -5
- meerschaum/connectors/valkey/__init__.py +3 -1
- meerschaum/connectors/valkey/_pipes.py +13 -8
- meerschaum/core/Pipe/__init__.py +1 -0
- meerschaum/core/Pipe/_clear.py +16 -13
- meerschaum/core/Pipe/_copy.py +106 -0
- meerschaum/core/Pipe/_data.py +155 -100
- meerschaum/core/Pipe/_verify.py +11 -11
- meerschaum/jobs/_Job.py +1 -6
- meerschaum/jobs/__init__.py +7 -2
- meerschaum/utils/dataframe.py +4 -1
- meerschaum/utils/formatting/_shell.py +5 -6
- meerschaum/utils/packages/__init__.py +14 -9
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/METADATA +1 -1
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/RECORD +70 -69
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/WHEEL +1 -1
- meerschaum/api/dash/actions.py +0 -255
- /meerschaum/connectors/{Connector.py → _Connector.py} +0 -0
- /meerschaum/connectors/sql/{SQLConnector.py → _SQLConnector.py} +0 -0
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/LICENSE +0 -0
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/NOTICE +0 -0
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.4.0.dev0.dist-info → meerschaum-2.4.0rc1.dist-info}/zip-safe +0 -0
@@ -7,28 +7,13 @@ Execute Meerschaum Actions via the API
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
|
11
|
-
import
|
12
|
-
import shlex
|
13
|
-
from functools import partial
|
14
|
-
from datetime import datetime, timezone
|
15
|
-
|
16
|
-
from fastapi import WebSocket, WebSocketDisconnect
|
17
|
-
from websockets.exceptions import ConnectionClosedError
|
18
|
-
|
19
|
-
from meerschaum.utils.misc import generate_password
|
20
|
-
from meerschaum.jobs import Job
|
21
|
-
from meerschaum.utils.warnings import warn
|
22
|
-
from meerschaum.utils.typing import SuccessTuple, Union, List, Dict, Any
|
10
|
+
|
11
|
+
from meerschaum.utils.typing import SuccessTuple, List, Dict, Any
|
23
12
|
from meerschaum.api import (
|
24
13
|
fastapi, app, endpoints, get_api_connector, debug, manager, private, no_auth
|
25
14
|
)
|
26
15
|
from meerschaum.actions import actions
|
27
|
-
import meerschaum.core
|
28
16
|
from meerschaum.config import get_config
|
29
|
-
from meerschaum._internal.arguments._parse_arguments import parse_dict_to_sysargs, parse_arguments
|
30
|
-
from meerschaum.api.routes._jobs import clean_sysargs
|
31
|
-
from meerschaum.jobs._Job import StopMonitoringLogs
|
32
17
|
|
33
18
|
actions_endpoint = endpoints['actions']
|
34
19
|
|
@@ -82,7 +67,7 @@ def do_action_legacy(
|
|
82
67
|
----------
|
83
68
|
action: str
|
84
69
|
The action to perform.
|
85
|
-
|
70
|
+
|
86
71
|
keywords: Dict[str, Any]
|
87
72
|
The keywords dictionary to pass to the action.
|
88
73
|
|
@@ -91,7 +76,6 @@ def do_action_legacy(
|
|
91
76
|
A `SuccessTuple`.
|
92
77
|
"""
|
93
78
|
if curr_user is not None and curr_user.type != 'admin':
|
94
|
-
from meerschaum.config import get_config
|
95
79
|
allow_non_admin = get_config(
|
96
80
|
'system', 'api', 'permissions', 'actions', 'non_admin', patch=True
|
97
81
|
)
|
@@ -103,7 +87,7 @@ def do_action_legacy(
|
|
103
87
|
+ "and search for 'permissions'. "
|
104
88
|
+ "\nUnder the keys 'api:permissions:actions', "
|
105
89
|
+ "you can allow non-admin users to perform actions."
|
106
|
-
|
90
|
+
)
|
107
91
|
|
108
92
|
if action not in actions:
|
109
93
|
return False, f"Invalid action '{action}'."
|
meerschaum/api/routes/_jobs.py
CHANGED
@@ -9,7 +9,6 @@ Manage jobs via the Meerschaum API.
|
|
9
9
|
from __future__ import annotations
|
10
10
|
|
11
11
|
import os
|
12
|
-
import select
|
13
12
|
import asyncio
|
14
13
|
import traceback
|
15
14
|
from datetime import datetime
|
@@ -18,12 +17,10 @@ from functools import partial
|
|
18
17
|
|
19
18
|
from fastapi import WebSocket, WebSocketDisconnect
|
20
19
|
|
21
|
-
from meerschaum.utils.typing import Dict, Any, SuccessTuple, List,
|
20
|
+
from meerschaum.utils.typing import Dict, Any, SuccessTuple, List, Union
|
22
21
|
from meerschaum.jobs import (
|
23
22
|
get_jobs as _get_jobs,
|
24
23
|
Job,
|
25
|
-
StopMonitoringLogs,
|
26
|
-
get_executor_keys_from_context,
|
27
24
|
)
|
28
25
|
from meerschaum.utils.warnings import warn
|
29
26
|
|
@@ -32,14 +29,13 @@ from meerschaum.api import (
|
|
32
29
|
app,
|
33
30
|
endpoints,
|
34
31
|
manager,
|
35
|
-
debug,
|
36
32
|
no_auth,
|
37
|
-
private,
|
38
33
|
)
|
39
34
|
from meerschaum.config.static import STATIC_CONFIG
|
40
35
|
|
41
36
|
JOBS_STDIN_MESSAGE: str = STATIC_CONFIG['api']['jobs']['stdin_message']
|
42
37
|
JOBS_STOP_MESSAGE: str = STATIC_CONFIG['api']['jobs']['stop_message']
|
38
|
+
NONINTERACTIVE_ENV: str = STATIC_CONFIG['environment']['noninteractive']
|
43
39
|
EXECUTOR_KEYS: str = 'local'
|
44
40
|
|
45
41
|
|
@@ -48,7 +44,8 @@ def _get_job(name: str):
|
|
48
44
|
if systemd_job.exists():
|
49
45
|
return systemd_job
|
50
46
|
|
51
|
-
|
47
|
+
job = Job(name, executor_keys=EXECUTOR_KEYS)
|
48
|
+
return job
|
52
49
|
|
53
50
|
|
54
51
|
@app.get(endpoints['jobs'], tags=['Jobs'])
|
@@ -150,6 +147,10 @@ def create_job(
|
|
150
147
|
name,
|
151
148
|
clean_sysargs(sysargs),
|
152
149
|
executor_keys=EXECUTOR_KEYS,
|
150
|
+
env={
|
151
|
+
NONINTERACTIVE_ENV: '1',
|
152
|
+
**dict(os.environ)
|
153
|
+
},
|
153
154
|
_properties=properties,
|
154
155
|
)
|
155
156
|
if job.exists():
|
@@ -8,10 +8,9 @@ Routes to the Webterm proxy.
|
|
8
8
|
|
9
9
|
import asyncio
|
10
10
|
from meerschaum.utils.typing import Optional
|
11
|
-
from meerschaum.api import app,
|
11
|
+
from meerschaum.api import app, endpoints
|
12
12
|
from meerschaum.utils.packages import attempt_import
|
13
|
-
from meerschaum.api.dash import
|
14
|
-
from meerschaum.api.dash.users import is_session_authenticated
|
13
|
+
from meerschaum.api.dash.sessions import is_session_authenticated
|
15
14
|
fastapi, fastapi_responses = attempt_import('fastapi', 'fastapi.responses')
|
16
15
|
import starlette
|
17
16
|
httpx = attempt_import('httpx')
|
@@ -25,9 +24,9 @@ PlainTextResponse = fastapi_responses.PlainTextResponse
|
|
25
24
|
|
26
25
|
@app.get(endpoints['webterm'], tags=["Webterm"])
|
27
26
|
async def get_webterm(
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
request: Request,
|
28
|
+
s: Optional[str] = None,
|
29
|
+
) -> HTMLResponse:
|
31
30
|
"""
|
32
31
|
Get the main HTML template for the Webterm.
|
33
32
|
"""
|
meerschaum/config/_default.py
CHANGED
@@ -96,6 +96,10 @@ default_system_config = {
|
|
96
96
|
'proxy_headers': True,
|
97
97
|
'forwarded_allow_ips': '*',
|
98
98
|
},
|
99
|
+
'cache': {
|
100
|
+
'connector': 'valkey:main',
|
101
|
+
'session_expires_minutes': 43200,
|
102
|
+
},
|
99
103
|
'permissions': {
|
100
104
|
'registration': {
|
101
105
|
'users': True,
|
@@ -105,7 +109,7 @@ default_system_config = {
|
|
105
109
|
'actions': {
|
106
110
|
'non_admin': True,
|
107
111
|
},
|
108
|
-
'chaining'
|
112
|
+
'chaining': {
|
109
113
|
'insecure_parent_instance': False,
|
110
114
|
'child_apis': False,
|
111
115
|
},
|
@@ -120,6 +124,7 @@ default_system_config = {
|
|
120
124
|
'inplace_sync': True,
|
121
125
|
'uv_pip': True,
|
122
126
|
'systemd_healthcheck': False,
|
127
|
+
'valkey_session_cache': True,
|
123
128
|
},
|
124
129
|
}
|
125
130
|
default_pipes_config = {
|
meerschaum/config/_version.py
CHANGED
@@ -52,8 +52,8 @@ env_dict = {
|
|
52
52
|
### apply patch to host config to change hostname to the Docker service name
|
53
53
|
env_dict['MEERSCHAUM_API_CONFIG'] = json.dumps(
|
54
54
|
{
|
55
|
-
'meerschaum'
|
56
|
-
'system'
|
55
|
+
'meerschaum': 'MRSM{!meerschaum}',
|
56
|
+
'system': 'MRSM{!system}',
|
57
57
|
},
|
58
58
|
indent = 4,
|
59
59
|
).replace(
|
@@ -82,12 +82,14 @@ env_dict['MEERSCHAUM_API_PATCH'] = json.dumps(
|
|
82
82
|
'port': 5432,
|
83
83
|
},
|
84
84
|
'local': {
|
85
|
-
'database': volumes['api_root'] + '/sqlite/mrsm_local.db'
|
85
|
+
'database': volumes['api_root'] + '/sqlite/mrsm_local.db',
|
86
86
|
},
|
87
87
|
},
|
88
88
|
'valkey': {
|
89
|
-
'
|
90
|
-
|
89
|
+
'main': {
|
90
|
+
'host': valkey_host,
|
91
|
+
'port': 6379,
|
92
|
+
},
|
91
93
|
},
|
92
94
|
},
|
93
95
|
},
|
@@ -133,7 +135,7 @@ default_docker_compose_config = {
|
|
133
135
|
'ports': [
|
134
136
|
f'{db_port}:5432',
|
135
137
|
],
|
136
|
-
'hostname':
|
138
|
+
'hostname': db_hostname,
|
137
139
|
'volumes': [
|
138
140
|
'meerschaum_db_data:' + volumes['meerschaum_db_data'],
|
139
141
|
],
|
@@ -178,7 +180,7 @@ default_docker_compose_config = {
|
|
178
180
|
],
|
179
181
|
},
|
180
182
|
'valkey': {
|
181
|
-
'image': 'bitnami/valkey',
|
183
|
+
'image': 'bitnami/valkey:latest',
|
182
184
|
'restart': 'always',
|
183
185
|
'environment': {
|
184
186
|
'VALKEY_PASSWORD': '<DOLLAR>VALKEY_PASSWORD',
|
@@ -53,6 +53,9 @@ STATIC_CONFIG: Dict[str, Any] = {
|
|
53
53
|
'internal_schema': '_mrsm_internal',
|
54
54
|
'instance_schema': 'mrsm',
|
55
55
|
},
|
56
|
+
'valkey': {
|
57
|
+
'colon': '-_',
|
58
|
+
},
|
56
59
|
'environment': {
|
57
60
|
'config': 'MRSM_CONFIG',
|
58
61
|
'config_dir': 'MRSM_CONFIG_DIR',
|
@@ -69,6 +72,7 @@ STATIC_CONFIG: Dict[str, Any] = {
|
|
69
72
|
'uid': 'MRSM_UID',
|
70
73
|
'gid': 'MRSM_GID',
|
71
74
|
'noask': 'MRSM_NOASK',
|
75
|
+
'noninteractive': 'MRSM_NONINTERACTIVE',
|
72
76
|
'id': 'MRSM_SERVER_ID',
|
73
77
|
'daemon_id': 'MRSM_DAEMON_ID',
|
74
78
|
'systemd_log_path': 'MRSM_SYSTEMD_LOG_PATH',
|
@@ -14,13 +14,13 @@ For ease of use, you can also import from the root `meerschaum` module:
|
|
14
14
|
from __future__ import annotations
|
15
15
|
|
16
16
|
import meerschaum as mrsm
|
17
|
-
from meerschaum.utils.typing import Any,
|
18
|
-
from meerschaum.utils.threading import
|
19
|
-
from meerschaum.utils.warnings import
|
17
|
+
from meerschaum.utils.typing import Any, Union, List, Dict
|
18
|
+
from meerschaum.utils.threading import RLock
|
19
|
+
from meerschaum.utils.warnings import warn
|
20
20
|
|
21
|
-
from meerschaum.connectors.
|
22
|
-
from meerschaum.connectors.sql.
|
23
|
-
from meerschaum.connectors.api.
|
21
|
+
from meerschaum.connectors._Connector import Connector, InvalidAttributesError
|
22
|
+
from meerschaum.connectors.sql._SQLConnector import SQLConnector
|
23
|
+
from meerschaum.connectors.api._APIConnector import APIConnector
|
24
24
|
from meerschaum.connectors.sql._create_engine import flavor_configs as sql_flavor_configs
|
25
25
|
|
26
26
|
__all__ = (
|
@@ -31,6 +31,9 @@ __all__ = (
|
|
31
31
|
"get_connector",
|
32
32
|
"is_connected",
|
33
33
|
"poll",
|
34
|
+
"api",
|
35
|
+
"sql",
|
36
|
+
"valkey",
|
34
37
|
)
|
35
38
|
|
36
39
|
### store connectors partitioned by
|
@@ -54,7 +57,10 @@ attributes: Dict[str, Dict[str, Any]] = {
|
|
54
57
|
'required': [
|
55
58
|
'host',
|
56
59
|
'username',
|
57
|
-
'password'
|
60
|
+
'password',
|
61
|
+
],
|
62
|
+
'optional': [
|
63
|
+
'port',
|
58
64
|
],
|
59
65
|
'default': {
|
60
66
|
'protocol': 'http',
|
@@ -263,11 +269,11 @@ def is_connected(keys: str, **kw) -> bool:
|
|
263
269
|
|
264
270
|
try:
|
265
271
|
typ, label = keys.split(':')
|
266
|
-
except Exception
|
272
|
+
except Exception:
|
267
273
|
return False
|
268
274
|
if typ not in instance_types:
|
269
275
|
return False
|
270
|
-
if not
|
276
|
+
if label not in connectors.get(typ, {}):
|
271
277
|
return False
|
272
278
|
|
273
279
|
from meerschaum.connectors.parse import parse_instance_keys
|
@@ -7,7 +7,7 @@ Interact with Meerschaum APIs. May be chained together (see 'meerschaum:api_inst
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from datetime import datetime, timedelta, timezone
|
10
|
-
from meerschaum.utils.typing import Optional
|
10
|
+
from meerschaum.utils.typing import Optional, List
|
11
11
|
from meerschaum.connectors import Connector
|
12
12
|
from meerschaum.utils.warnings import warn, error
|
13
13
|
from meerschaum.utils.packages import attempt_import
|
@@ -24,6 +24,8 @@ class APIConnector(Connector):
|
|
24
24
|
IS_INSTANCE: bool = True
|
25
25
|
IS_THREAD_SAFE: bool = False
|
26
26
|
|
27
|
+
OPTIONAL_ATTRIBUTES: List[str] = ['port']
|
28
|
+
|
27
29
|
from ._request import (
|
28
30
|
make_request,
|
29
31
|
get,
|
meerschaum/connectors/parse.py
CHANGED
@@ -7,7 +7,10 @@ Utility functions for parsing connector keys.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
|
10
|
+
|
11
|
+
import meerschaum as mrsm
|
12
|
+
from meerschaum.utils.typing import Any, Union, Optional, Dict, Tuple
|
13
|
+
|
11
14
|
|
12
15
|
def parse_connector_keys(
|
13
16
|
keys: str,
|
@@ -15,20 +18,20 @@ def parse_connector_keys(
|
|
15
18
|
as_tuple: bool = False,
|
16
19
|
**kw: Any
|
17
20
|
) -> (
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
],
|
27
|
-
str
|
21
|
+
Union[
|
22
|
+
mrsm.connectors.Connector,
|
23
|
+
Dict[str, Any],
|
24
|
+
Tuple[
|
25
|
+
Union[
|
26
|
+
mrsm.connectors.Connector,
|
27
|
+
Dict[str, Any],
|
28
|
+
None,
|
28
29
|
],
|
29
|
-
|
30
|
-
]
|
31
|
-
|
30
|
+
str
|
31
|
+
],
|
32
|
+
None
|
33
|
+
]
|
34
|
+
):
|
32
35
|
"""
|
33
36
|
Convenience function for parsing connector keys and returning Connector objects.
|
34
37
|
|
@@ -95,13 +98,12 @@ def parse_instance_keys(
|
|
95
98
|
"""
|
96
99
|
Parse the Meerschaum instance value into a Connector object.
|
97
100
|
"""
|
98
|
-
from meerschaum.utils.warnings import warn
|
99
101
|
from meerschaum.config import get_config
|
100
102
|
|
101
103
|
if keys is None:
|
102
104
|
keys = get_config('meerschaum', 'instance')
|
103
105
|
keys = str(keys)
|
104
|
-
|
106
|
+
|
105
107
|
return parse_connector_keys(keys, construct=construct, as_tuple=as_tuple, **kw)
|
106
108
|
|
107
109
|
|
@@ -821,7 +821,8 @@ def get_pipe_data_query(
|
|
821
821
|
begin: Union[datetime, int, str, None] = None,
|
822
822
|
end: Union[datetime, int, str, None] = None,
|
823
823
|
params: Optional[Dict[str, Any]] = None,
|
824
|
-
order: str = 'asc',
|
824
|
+
order: Optional[str] = 'asc',
|
825
|
+
sort_datetimes: bool = False,
|
825
826
|
limit: Optional[int] = None,
|
826
827
|
begin_add_minutes: int = 0,
|
827
828
|
end_add_minutes: int = 0,
|
@@ -854,10 +855,13 @@ def get_pipe_data_query(
|
|
854
855
|
Additional parameters to filter by.
|
855
856
|
See `meerschaum.connectors.sql.build_where`.
|
856
857
|
|
857
|
-
order: Optional[str], default
|
858
|
+
order: Optional[str], default None
|
858
859
|
The selection order for all of the indices in the query.
|
859
860
|
If `None`, omit the `ORDER BY` clause.
|
860
861
|
|
862
|
+
sort_datetimes: bool, default False
|
863
|
+
Alias for `order='desc'`.
|
864
|
+
|
861
865
|
limit: Optional[int], default None
|
862
866
|
If specified, limit the number of rows retrieved to this value.
|
863
867
|
|
@@ -880,7 +884,6 @@ def get_pipe_data_query(
|
|
880
884
|
-------
|
881
885
|
A `SELECT` query to retrieve a pipe's data.
|
882
886
|
"""
|
883
|
-
import json
|
884
887
|
from meerschaum.utils.debug import dprint
|
885
888
|
from meerschaum.utils.misc import items_str
|
886
889
|
from meerschaum.utils.sql import sql_item_name, dateadd_str
|
@@ -895,6 +898,9 @@ def get_pipe_data_query(
|
|
895
898
|
if omit_columns:
|
896
899
|
select_columns = [col for col in select_columns if col not in omit_columns]
|
897
900
|
|
901
|
+
if order is None and sort_datetimes:
|
902
|
+
order = 'desc'
|
903
|
+
|
898
904
|
if begin == '':
|
899
905
|
begin = pipe.get_sync_time(debug=debug)
|
900
906
|
backtrack_interval = pipe.get_backtrack_interval(debug=debug)
|
@@ -960,10 +966,10 @@ def get_pipe_data_query(
|
|
960
966
|
is_dt_bound = False
|
961
967
|
if begin is not None and _dt in existing_cols:
|
962
968
|
begin_da = dateadd_str(
|
963
|
-
flavor
|
964
|
-
datepart
|
965
|
-
number
|
966
|
-
begin
|
969
|
+
flavor=self.flavor,
|
970
|
+
datepart='minute',
|
971
|
+
number=begin_add_minutes,
|
972
|
+
begin=begin,
|
967
973
|
)
|
968
974
|
where += f"{dt} >= {begin_da}" + (" AND " if end is not None else "")
|
969
975
|
is_dt_bound = True
|
@@ -972,10 +978,10 @@ def get_pipe_data_query(
|
|
972
978
|
if 'int' in str(type(end)).lower() and end == begin:
|
973
979
|
end += 1
|
974
980
|
end_da = dateadd_str(
|
975
|
-
flavor
|
976
|
-
datepart
|
977
|
-
number
|
978
|
-
begin
|
981
|
+
flavor=self.flavor,
|
982
|
+
datepart='minute',
|
983
|
+
number=end_add_minutes,
|
984
|
+
begin=end
|
979
985
|
)
|
980
986
|
where += f"{dt} < {end_da}"
|
981
987
|
is_dt_bound = True
|
@@ -1599,45 +1605,39 @@ def sync_pipe_inplace(
|
|
1599
1605
|
|
1600
1606
|
backtrack_def = self.get_pipe_data_query(
|
1601
1607
|
pipe,
|
1602
|
-
begin
|
1603
|
-
end
|
1604
|
-
begin_add_minutes
|
1605
|
-
end_add_minutes
|
1606
|
-
params
|
1607
|
-
debug
|
1608
|
-
order
|
1608
|
+
begin=begin,
|
1609
|
+
end=end,
|
1610
|
+
begin_add_minutes=0,
|
1611
|
+
end_add_minutes=1,
|
1612
|
+
params=params,
|
1613
|
+
debug=debug,
|
1614
|
+
order=None,
|
1609
1615
|
)
|
1610
1616
|
|
1611
|
-
select_backtrack_query = format_cte_subquery(
|
1612
|
-
backtrack_def,
|
1613
|
-
self.flavor,
|
1614
|
-
sub_name = 'backtrack_def',
|
1615
|
-
)
|
1616
1617
|
create_backtrack_query = get_create_table_query(
|
1617
1618
|
backtrack_def,
|
1618
1619
|
temp_tables['backtrack'],
|
1619
1620
|
self.flavor,
|
1620
|
-
schema
|
1621
|
+
schema=internal_schema,
|
1621
1622
|
)
|
1622
1623
|
(create_backtrack_success, create_backtrack_msg), create_backtrack_results = session_execute(
|
1623
1624
|
session,
|
1624
1625
|
create_backtrack_query,
|
1625
|
-
with_results
|
1626
|
-
debug
|
1626
|
+
with_results=True,
|
1627
|
+
debug=debug,
|
1627
1628
|
) if not upsert else (True, "Success"), None
|
1628
1629
|
|
1629
1630
|
if not create_backtrack_success:
|
1630
1631
|
_ = clean_up_temp_tables()
|
1631
1632
|
return create_backtrack_success, create_backtrack_msg
|
1632
|
-
bactrack_count = create_backtrack_results[0].rowcount if create_backtrack_results else 0
|
1633
1633
|
|
1634
1634
|
backtrack_cols_types = get_table_cols_types(
|
1635
1635
|
temp_tables['backtrack'],
|
1636
|
-
connectable
|
1637
|
-
flavor
|
1638
|
-
schema
|
1639
|
-
database
|
1640
|
-
debug
|
1636
|
+
connectable=connectable,
|
1637
|
+
flavor=self.flavor,
|
1638
|
+
schema=internal_schema,
|
1639
|
+
database=database,
|
1640
|
+
debug=debug,
|
1641
1641
|
) if not upsert else new_cols_types
|
1642
1642
|
|
1643
1643
|
common_cols = [col for col in new_cols if col in backtrack_cols_types]
|
@@ -1663,7 +1663,7 @@ def sync_pipe_inplace(
|
|
1663
1663
|
)
|
1664
1664
|
|
1665
1665
|
select_delta_query = (
|
1666
|
-
|
1666
|
+
"SELECT\n"
|
1667
1667
|
+ null_replace_new_cols_str + "\n"
|
1668
1668
|
+ f"\nFROM {temp_table_names['new']}\n"
|
1669
1669
|
+ f"LEFT OUTER JOIN {temp_table_names['backtrack']}\nON\n"
|
@@ -1693,12 +1693,12 @@ def sync_pipe_inplace(
|
|
1693
1693
|
select_delta_query,
|
1694
1694
|
temp_tables['delta'],
|
1695
1695
|
self.flavor,
|
1696
|
-
schema
|
1696
|
+
schema=internal_schema,
|
1697
1697
|
)
|
1698
1698
|
create_delta_success, create_delta_msg = session_execute(
|
1699
1699
|
session,
|
1700
1700
|
create_delta_query,
|
1701
|
-
debug
|
1701
|
+
debug=debug,
|
1702
1702
|
) if not upsert else (True, "Success")
|
1703
1703
|
if not create_delta_success:
|
1704
1704
|
_ = clean_up_temp_tables()
|
@@ -1707,10 +1707,10 @@ def sync_pipe_inplace(
|
|
1707
1707
|
delta_cols_types = get_table_cols_types(
|
1708
1708
|
temp_tables['delta'],
|
1709
1709
|
connectable = connectable,
|
1710
|
-
flavor
|
1711
|
-
schema
|
1712
|
-
database
|
1713
|
-
debug
|
1710
|
+
flavor=self.flavor,
|
1711
|
+
schema=internal_schema,
|
1712
|
+
database=database,
|
1713
|
+
debug=debug,
|
1714
1714
|
) if not upsert else new_cols_types
|
1715
1715
|
|
1716
1716
|
### This is a weird bug on SQLite.
|
@@ -11,9 +11,8 @@ from datetime import datetime, timezone
|
|
11
11
|
|
12
12
|
import meerschaum as mrsm
|
13
13
|
from meerschaum.connectors import Connector, make_connector
|
14
|
-
from meerschaum.utils.typing import List, Dict, Any,
|
15
|
-
from meerschaum.utils.warnings import
|
16
|
-
from meerschaum.utils.misc import json_serialize_datetime
|
14
|
+
from meerschaum.utils.typing import List, Dict, Any, Optional, Union
|
15
|
+
from meerschaum.utils.warnings import dprint
|
17
16
|
|
18
17
|
|
19
18
|
@make_connector
|
@@ -141,11 +140,11 @@ class ValkeyConnector(Connector):
|
|
141
140
|
|
142
141
|
return uri
|
143
142
|
|
144
|
-
def set(self, key: str, value: Any) -> None:
|
143
|
+
def set(self, key: str, value: Any, **kwargs: Any) -> None:
|
145
144
|
"""
|
146
145
|
Set the `key` to `value`.
|
147
146
|
"""
|
148
|
-
return self.client.set(key, value)
|
147
|
+
return self.client.set(key, value, **kwargs)
|
149
148
|
|
150
149
|
def get(self, key: str) -> Union[str, None]:
|
151
150
|
"""
|
@@ -243,6 +242,7 @@ class ValkeyConnector(Connector):
|
|
243
242
|
-------
|
244
243
|
The current index counter value (how many docs have been pushed).
|
245
244
|
"""
|
245
|
+
from meerschaum.utils.misc import json_serialize_datetime
|
246
246
|
table_name = self.quote_table(table)
|
247
247
|
datetime_column_key = self.get_datetime_column_key(table)
|
248
248
|
remote_datetime_column = self.get(datetime_column_key)
|
@@ -6,15 +6,17 @@ Define pipes methods for `ValkeyConnector`.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import json
|
9
|
-
from datetime import datetime,
|
9
|
+
from datetime import datetime, timezone
|
10
10
|
|
11
11
|
import meerschaum as mrsm
|
12
12
|
from meerschaum.utils.typing import SuccessTuple, Any, Union, Optional, Dict, List, Tuple
|
13
13
|
from meerschaum.utils.misc import json_serialize_datetime, string_to_dict
|
14
|
-
from meerschaum.utils.warnings import
|
14
|
+
from meerschaum.utils.warnings import warn
|
15
|
+
from meerschaum.config.static import STATIC_CONFIG
|
15
16
|
|
16
17
|
PIPES_TABLE: str = 'mrsm_pipes'
|
17
18
|
PIPES_COUNTER: str = 'mrsm_pipes:counter'
|
19
|
+
COLON: str = STATIC_CONFIG['valkey']['colon']
|
18
20
|
|
19
21
|
|
20
22
|
def get_pipe_key(pipe: mrsm.Pipe) -> str:
|
@@ -88,7 +90,7 @@ def get_document_key(
|
|
88
90
|
indices_str = ((table_name + ':indices:') if table_name else '') + ','.join(
|
89
91
|
sorted(
|
90
92
|
[
|
91
|
-
f'{key}
|
93
|
+
f'{key}{COLON}{val}'
|
92
94
|
for key, val in index_vals.items()
|
93
95
|
]
|
94
96
|
)
|
@@ -413,7 +415,7 @@ def get_pipe_data(
|
|
413
415
|
table_name = self.quote_table(pipe.target)
|
414
416
|
indices = [col for col in pipe.columns.values() if col]
|
415
417
|
ix_docs = [
|
416
|
-
string_to_dict(doc['ix'])
|
418
|
+
string_to_dict(doc['ix'].replace(COLON, ':'))
|
417
419
|
for doc in self.read_docs(
|
418
420
|
pipe.target,
|
419
421
|
begin=begin,
|
@@ -505,6 +507,7 @@ def sync_pipe(
|
|
505
507
|
is_dask = 'dask' in df.__module__
|
506
508
|
if is_dask:
|
507
509
|
df = df.compute()
|
510
|
+
upsert = pipe.parameters.get('upsert', False)
|
508
511
|
|
509
512
|
def _serialize_indices_docs(_docs):
|
510
513
|
return [
|
@@ -546,16 +549,18 @@ def sync_pipe(
|
|
546
549
|
if not edit_success:
|
547
550
|
return edit_success, edit_msg
|
548
551
|
|
549
|
-
# df = pipe.enforce_dtypes(df, debug=debug)
|
550
|
-
|
551
552
|
unseen_df, update_df, delta_df = (
|
552
553
|
pipe.filter_existing(df, include_unchanged_columns=True, debug=debug)
|
553
|
-
if check_existing
|
554
|
+
if check_existing and not upsert
|
554
555
|
else (df, None, df)
|
555
556
|
)
|
556
557
|
num_insert = len(unseen_df) if unseen_df is not None else 0
|
557
558
|
num_update = len(update_df) if update_df is not None else 0
|
558
|
-
msg =
|
559
|
+
msg = (
|
560
|
+
f"Inserted {num_insert}, updated {num_update} rows."
|
561
|
+
if not upsert
|
562
|
+
else f"Upserted {num_insert} rows."
|
563
|
+
)
|
559
564
|
if len(delta_df) == 0:
|
560
565
|
return True, msg
|
561
566
|
|