meerschaum 2.5.0__py3-none-any.whl → 2.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerschaum/_internal/arguments/_parser.py +6 -1
- meerschaum/_internal/entry.py +16 -5
- meerschaum/actions/edit.py +6 -6
- meerschaum/actions/sql.py +12 -11
- meerschaum/api/dash/pages/login.py +17 -17
- meerschaum/api/dash/pipes.py +104 -13
- meerschaum/api/routes/_pipes.py +58 -40
- meerschaum/api/routes/_webterm.py +1 -0
- meerschaum/config/_edit.py +46 -19
- meerschaum/config/_read_config.py +20 -9
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +1 -1
- meerschaum/config/static/__init__.py +1 -0
- meerschaum/connectors/api/_APIConnector.py +1 -0
- meerschaum/connectors/api/_pipes.py +39 -8
- meerschaum/connectors/sql/_SQLConnector.py +4 -3
- meerschaum/connectors/sql/_pipes.py +511 -118
- meerschaum/connectors/sql/_sql.py +55 -15
- meerschaum/connectors/valkey/_ValkeyConnector.py +3 -2
- meerschaum/connectors/valkey/_pipes.py +11 -5
- meerschaum/core/Pipe/__init__.py +27 -9
- meerschaum/core/Pipe/_attributes.py +181 -18
- meerschaum/core/Pipe/_clear.py +10 -8
- meerschaum/core/Pipe/_copy.py +2 -0
- meerschaum/core/Pipe/_data.py +65 -17
- meerschaum/core/Pipe/_deduplicate.py +30 -28
- meerschaum/core/Pipe/_dtypes.py +4 -4
- meerschaum/core/Pipe/_fetch.py +12 -10
- meerschaum/core/Pipe/_sync.py +28 -11
- meerschaum/core/Pipe/_verify.py +52 -49
- meerschaum/utils/dataframe.py +64 -34
- meerschaum/utils/dtypes/__init__.py +25 -6
- meerschaum/utils/dtypes/sql.py +76 -33
- meerschaum/utils/misc.py +57 -24
- meerschaum/utils/packages/_packages.py +2 -1
- meerschaum/utils/schedule.py +7 -5
- meerschaum/utils/sql.py +697 -44
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/METADATA +5 -3
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/RECORD +45 -45
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/WHEEL +1 -1
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/LICENSE +0 -0
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/NOTICE +0 -0
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.5.0.dist-info → meerschaum-2.6.0.dist-info}/zip-safe +0 -0
@@ -6,22 +6,26 @@ Import the config yaml file
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from __future__ import annotations
|
9
|
+
import pathlib
|
10
|
+
|
9
11
|
from meerschaum.utils.typing import Optional, Dict, Any, List, Tuple, Union
|
10
12
|
from meerschaum.config import get_config
|
11
13
|
|
14
|
+
|
12
15
|
def read_config(
|
13
|
-
directory:
|
16
|
+
directory: Union[pathlib.Path, str, None] = None,
|
14
17
|
keys: Optional[List[str]] = None,
|
15
|
-
write_missing
|
16
|
-
substitute
|
17
|
-
with_filenames
|
18
|
+
write_missing: bool = True,
|
19
|
+
substitute: bool = True,
|
20
|
+
with_filenames: bool = False,
|
21
|
+
raise_parsing_errors: bool = False,
|
18
22
|
) -> Union[Dict[str, Any], Tuple[Dict[str, Any], List[str]]]:
|
19
23
|
"""
|
20
24
|
Read the configuration directory.
|
21
25
|
|
22
26
|
Parameters
|
23
27
|
----------
|
24
|
-
directory:
|
28
|
+
directory: Union[pathlib.Path, str, None], default None
|
25
29
|
The directory with configuration files (.json and .yaml).
|
26
30
|
|
27
31
|
keys: Optional[List[str]], default None
|
@@ -36,7 +40,10 @@ def read_config(
|
|
36
40
|
|
37
41
|
with_filename: bool, default False
|
38
42
|
If `True`, return a tuple of the configuration dictionary with a list of read filenames.
|
39
|
-
|
43
|
+
|
44
|
+
raise_parsing_errors: bool, default False
|
45
|
+
If `True`, re-raise parsing exceptions.
|
46
|
+
|
40
47
|
Examples
|
41
48
|
--------
|
42
49
|
>>> read_config(keys=['meerschaum'], with_filename=True)
|
@@ -63,9 +70,9 @@ def read_config(
|
|
63
70
|
|
64
71
|
default_filetype = STATIC_CONFIG['config']['default_filetype']
|
65
72
|
filetype_loaders = {
|
66
|
-
'yml'
|
67
|
-
'yaml'
|
68
|
-
'json'
|
73
|
+
'yml': yaml.load,
|
74
|
+
'yaml': yaml.load,
|
75
|
+
'json': json.load,
|
69
76
|
}
|
70
77
|
|
71
78
|
### Construct filekeys (files to parse).
|
@@ -167,6 +174,8 @@ def read_config(
|
|
167
174
|
_config_key = filetype_loaders[_type](f)
|
168
175
|
except Exception as e:
|
169
176
|
print(f"Error processing file: {filepath}")
|
177
|
+
if raise_parsing_errors:
|
178
|
+
raise e
|
170
179
|
import traceback
|
171
180
|
traceback.print_exc()
|
172
181
|
_config_key = {}
|
@@ -184,6 +193,8 @@ def read_config(
|
|
184
193
|
config[symlinks_key][key] = _single_key_config[symlinks_key][key]
|
185
194
|
break
|
186
195
|
except Exception as e:
|
196
|
+
if raise_parsing_errors:
|
197
|
+
raise e
|
187
198
|
print(f"Unable to parse {filename}!")
|
188
199
|
import traceback
|
189
200
|
traceback.print_exc()
|
meerschaum/config/_version.py
CHANGED
@@ -39,7 +39,7 @@ valkey_password = 'MRSM{meerschaum:connectors:valkey:main:password}'
|
|
39
39
|
|
40
40
|
env_dict = {
|
41
41
|
'COMPOSE_PROJECT_NAME': 'mrsm',
|
42
|
-
'TIMESCALEDB_VERSION': 'latest-pg16
|
42
|
+
'TIMESCALEDB_VERSION': 'latest-pg16',
|
43
43
|
'POSTGRES_USER': db_user,
|
44
44
|
'POSTGRES_PASSWORD': db_pass,
|
45
45
|
'POSTGRES_DB': db_base,
|
@@ -669,11 +669,11 @@ def clear_pipe(
|
|
669
669
|
kw.pop('force', None)
|
670
670
|
return self.do_action_legacy(
|
671
671
|
['clear', 'pipes'],
|
672
|
-
connector_keys
|
673
|
-
metric_keys
|
674
|
-
location_keys
|
675
|
-
force
|
676
|
-
debug
|
672
|
+
connector_keys=pipe.connector_keys,
|
673
|
+
metric_keys=pipe.metric_key,
|
674
|
+
location_keys=pipe.location_key,
|
675
|
+
force=True,
|
676
|
+
debug=debug,
|
677
677
|
**kw
|
678
678
|
)
|
679
679
|
|
@@ -690,7 +690,7 @@ def get_pipe_columns_types(
|
|
690
690
|
----------
|
691
691
|
pipe: meerschaum.Pipe
|
692
692
|
The pipe whose columns to be queried.
|
693
|
-
|
693
|
+
|
694
694
|
Returns
|
695
695
|
-------
|
696
696
|
A dictionary mapping column names to their database types.
|
@@ -707,11 +707,42 @@ def get_pipe_columns_types(
|
|
707
707
|
r_url = pipe_r_url(pipe) + '/columns/types'
|
708
708
|
response = self.get(
|
709
709
|
r_url,
|
710
|
-
debug
|
710
|
+
debug=debug
|
711
|
+
)
|
712
|
+
j = response.json()
|
713
|
+
if isinstance(j, dict) and 'detail' in j and len(j.keys()) == 1:
|
714
|
+
warn(j['detail'])
|
715
|
+
return None
|
716
|
+
if not isinstance(j, dict):
|
717
|
+
warn(response.text)
|
718
|
+
return None
|
719
|
+
return j
|
720
|
+
|
721
|
+
|
722
|
+
def get_pipe_columns_indices(
|
723
|
+
self,
|
724
|
+
pipe: mrsm.Pipe,
|
725
|
+
debug: bool = False,
|
726
|
+
) -> Union[Dict[str, str], None]:
|
727
|
+
"""
|
728
|
+
Fetch the index information for a pipe.
|
729
|
+
|
730
|
+
Parameters
|
731
|
+
----------
|
732
|
+
pipe: mrsm.Pipe
|
733
|
+
The pipe whose columns to be queried.
|
734
|
+
|
735
|
+
Returns
|
736
|
+
-------
|
737
|
+
A dictionary mapping column names to a list of associated index information.
|
738
|
+
"""
|
739
|
+
r_url = pipe_r_url(pipe) + '/columns/indices'
|
740
|
+
response = self.get(
|
741
|
+
r_url,
|
742
|
+
debug=debug
|
711
743
|
)
|
712
744
|
j = response.json()
|
713
745
|
if isinstance(j, dict) and 'detail' in j and len(j.keys()) == 1:
|
714
|
-
from meerschaum.utils.warnings import warn
|
715
746
|
warn(j['detail'])
|
716
747
|
return None
|
717
748
|
if not isinstance(j, dict):
|
@@ -67,6 +67,8 @@ class SQLConnector(Connector):
|
|
67
67
|
get_pipe_columns_types,
|
68
68
|
get_to_sql_dtype,
|
69
69
|
get_pipe_schema,
|
70
|
+
create_pipe_table_from_df,
|
71
|
+
get_pipe_columns_indices,
|
70
72
|
)
|
71
73
|
from ._plugins import (
|
72
74
|
register_plugin,
|
@@ -141,9 +143,9 @@ class SQLConnector(Connector):
|
|
141
143
|
if uri.startswith('postgres') and not uri.startswith('postgresql'):
|
142
144
|
uri = uri.replace('postgres', 'postgresql', 1)
|
143
145
|
if uri.startswith('postgresql') and not uri.startswith('postgresql+'):
|
144
|
-
uri = uri.replace('postgresql://', 'postgresql+psycopg', 1)
|
146
|
+
uri = uri.replace('postgresql://', 'postgresql+psycopg://', 1)
|
145
147
|
if uri.startswith('timescaledb://'):
|
146
|
-
uri = uri.replace('timescaledb://', 'postgresql://', 1)
|
148
|
+
uri = uri.replace('timescaledb://', 'postgresql+psycopg://', 1)
|
147
149
|
flavor = 'timescaledb'
|
148
150
|
kw['uri'] = uri
|
149
151
|
from_uri_params = self.from_uri(kw['uri'], as_dict=True)
|
@@ -155,7 +157,6 @@ class SQLConnector(Connector):
|
|
155
157
|
if flavor:
|
156
158
|
kw['flavor'] = flavor
|
157
159
|
|
158
|
-
|
159
160
|
### set __dict__ in base class
|
160
161
|
super().__init__(
|
161
162
|
'sql',
|