meerschaum 2.5.1__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/actions/edit.py +6 -6
- meerschaum/actions/sql.py +12 -11
- meerschaum/api/dash/pages/login.py +17 -17
- meerschaum/api/dash/pipes.py +13 -4
- meerschaum/api/routes/_pipes.py +58 -40
- 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 +62 -32
- meerschaum/utils/dtypes/__init__.py +25 -6
- meerschaum/utils/dtypes/sql.py +76 -33
- meerschaum/utils/misc.py +57 -24
- meerschaum/utils/sql.py +697 -44
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/METADATA +1 -1
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/RECORD +41 -41
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/WHEEL +1 -1
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/LICENSE +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/NOTICE +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dist-info}/zip-safe +0 -0
@@ -90,8 +90,13 @@ def parse_datetime(dt_str: str) -> Union[datetime, int, str]:
|
|
90
90
|
except Exception as e:
|
91
91
|
dt = None
|
92
92
|
if dt is None:
|
93
|
-
from meerschaum.utils.warnings import
|
93
|
+
from meerschaum.utils.warnings import error
|
94
94
|
error(f"'{dt_str}' is not a valid datetime format.", stack=False)
|
95
|
+
|
96
|
+
if isinstance(dt, datetime):
|
97
|
+
from meerschaum.utils.dtypes import coerce_timezone
|
98
|
+
dt = coerce_timezone(dt)
|
99
|
+
|
95
100
|
return dt
|
96
101
|
|
97
102
|
|
meerschaum/actions/edit.py
CHANGED
@@ -65,24 +65,24 @@ def _complete_edit(
|
|
65
65
|
from meerschaum._internal.shell import default_action_completer
|
66
66
|
return default_action_completer(action=(['edit'] + action), **kw)
|
67
67
|
|
68
|
-
|
68
|
+
|
69
|
+
def _edit_config(action: Optional[List[str]] = None, **kw : Any) -> SuccessTuple:
|
69
70
|
"""
|
70
71
|
Edit Meerschaum configuration files.
|
71
|
-
|
72
|
+
|
72
73
|
Specify a specific configuration key to edit.
|
73
74
|
Defaults to editing `meerschaum` configuration (connectors, instance, etc.).
|
74
|
-
|
75
|
+
|
75
76
|
Examples:
|
76
77
|
```
|
77
78
|
### Edit the main 'meerschaum' configuration.
|
78
79
|
edit config
|
79
|
-
|
80
|
+
|
80
81
|
### Edit 'system' configuration.
|
81
82
|
edit config system
|
82
|
-
|
83
|
+
|
83
84
|
### Create a new configuration file called 'myconfig'.
|
84
85
|
edit config myconfig
|
85
|
-
|
86
86
|
```
|
87
87
|
"""
|
88
88
|
from meerschaum.config._edit import edit_config
|
meerschaum/actions/sql.py
CHANGED
@@ -14,6 +14,7 @@ exec_methods = {
|
|
14
14
|
'exec',
|
15
15
|
}
|
16
16
|
|
17
|
+
|
17
18
|
def sql(
|
18
19
|
action: Optional[List[str]] = None,
|
19
20
|
gui: bool = False,
|
@@ -22,40 +23,40 @@ def sql(
|
|
22
23
|
**kw: Any
|
23
24
|
):
|
24
25
|
"""Execute a SQL query or launch an interactive CLI. All positional arguments are optional.
|
25
|
-
|
26
|
+
|
26
27
|
Usage:
|
27
28
|
`sql {label} {method} {query / table}`
|
28
|
-
|
29
|
+
|
29
30
|
Options:
|
30
31
|
- `sql {label}`
|
31
32
|
Launch an interactive CLI. If {label} is omitted, use 'main'.
|
32
|
-
|
33
|
+
|
33
34
|
- `sql {label} read [query / table]`
|
34
35
|
Read a table or query as a pandas DataFrame and print the result.
|
35
|
-
|
36
|
+
|
36
37
|
- `sql {label} exec [query]`
|
37
38
|
Execute a query and print the success status.
|
38
|
-
|
39
|
+
|
39
40
|
Examples:
|
40
41
|
- `sql`
|
41
42
|
Open an interactive CLI for `sql:main`.
|
42
|
-
|
43
|
+
|
43
44
|
- `sql local`
|
44
45
|
Open an interactive CLI for `sql:local`.
|
45
|
-
|
46
|
+
|
46
47
|
- `sql table`
|
47
48
|
Read from `table` on `sql:main`
|
48
49
|
(translates to `SELECT * FROM table`).
|
49
|
-
|
50
|
+
|
50
51
|
- `sql local table`
|
51
52
|
Read from `table` on `sql:local`.
|
52
|
-
|
53
|
+
|
53
54
|
- `sql local read table`
|
54
55
|
Read from `table` on `sql:local`.
|
55
|
-
|
56
|
+
|
56
57
|
- `sql "SELECT * FROM table WHERE id = 1"`
|
57
58
|
Execute the above query on `sql:main` and print the results.
|
58
|
-
|
59
|
+
|
59
60
|
- `sql local exec "INSERT INTO table (id) VALUES (1)"
|
60
61
|
Execute the above query on `sql:local`.
|
61
62
|
"""
|
@@ -19,13 +19,13 @@ allow_user_registration = permissions_config['registration']['users']
|
|
19
19
|
|
20
20
|
registration_div = html.Div(
|
21
21
|
id = 'registration-div',
|
22
|
-
style
|
23
|
-
children
|
22
|
+
style={'height' : '100%'},
|
23
|
+
children=(
|
24
24
|
[
|
25
25
|
dcc.Link(
|
26
26
|
'No account? Create one here.',
|
27
|
-
href
|
28
|
-
refresh
|
27
|
+
href=(dash_endpoint + '/register'),
|
28
|
+
refresh=False
|
29
29
|
),
|
30
30
|
] if allow_user_registration
|
31
31
|
else [
|
@@ -36,12 +36,12 @@ registration_div = html.Div(
|
|
36
36
|
dbc.Button(
|
37
37
|
'More information.',
|
38
38
|
id = 'show-user-registration-disabled-button',
|
39
|
-
color
|
40
|
-
size
|
39
|
+
color='link',
|
40
|
+
size='sm',
|
41
41
|
),
|
42
42
|
dbc.Collapse(
|
43
|
-
id
|
44
|
-
children
|
43
|
+
id='user-registration-disabled-collapse',
|
44
|
+
children=[
|
45
45
|
dcc.Markdown(
|
46
46
|
"For example, to register user `newuser` on instance `sql:main`:"
|
47
47
|
),
|
@@ -60,10 +60,10 @@ registration_div = html.Div(
|
|
60
60
|
html.Pre(
|
61
61
|
html.Code(
|
62
62
|
json.dumps({
|
63
|
-
'api'
|
64
|
-
'permissions'
|
65
|
-
'registration'
|
66
|
-
'users'
|
63
|
+
'api': {
|
64
|
+
'permissions': {
|
65
|
+
'registration': {
|
66
|
+
'users': True,
|
67
67
|
},
|
68
68
|
}
|
69
69
|
}
|
@@ -112,11 +112,11 @@ layout = dbc.Container([
|
|
112
112
|
dbc.Row([
|
113
113
|
dbc.Col([
|
114
114
|
html.Button(
|
115
|
-
children
|
116
|
-
n_clicks
|
117
|
-
type
|
118
|
-
id
|
119
|
-
className
|
115
|
+
children='Login',
|
116
|
+
n_clicks=0,
|
117
|
+
type='submit',
|
118
|
+
id='login-button',
|
119
|
+
className='btn btn-primary btn-lg'
|
120
120
|
),
|
121
121
|
]),
|
122
122
|
]),
|
meerschaum/api/dash/pipes.py
CHANGED
@@ -33,6 +33,11 @@ html, dcc = import_html(check_update=CHECK_UPDATE), import_dcc(check_update=CHEC
|
|
33
33
|
humanfriendly = attempt_import('humanfriendly', check_update=CHECK_UPDATE)
|
34
34
|
pd = import_pandas()
|
35
35
|
|
36
|
+
INDEX_PREFIX_EMOJI: Dict[str, str] = {
|
37
|
+
'datetime': '🕓',
|
38
|
+
'primary': '🔑',
|
39
|
+
}
|
40
|
+
|
36
41
|
|
37
42
|
def pipe_from_ctx(ctx, trigger_property: str = 'n_clicks') -> Union[mrsm.Pipe, None]:
|
38
43
|
"""
|
@@ -420,9 +425,9 @@ def accordion_items_from_pipe(
|
|
420
425
|
columns = pipe.columns
|
421
426
|
index_column_names = pipe.get_indices()
|
422
427
|
indices_rows = []
|
423
|
-
for ix_key,
|
428
|
+
for ix_key, ix_cols in indices.items():
|
424
429
|
col = columns.get(ix_key, None)
|
425
|
-
|
430
|
+
ix_name = index_column_names.get(ix_key, None)
|
426
431
|
if not col and not ix_cols:
|
427
432
|
continue
|
428
433
|
if not isinstance(ix_cols, (list, tuple)):
|
@@ -434,12 +439,16 @@ def accordion_items_from_pipe(
|
|
434
439
|
else:
|
435
440
|
col_item = html.Pre(html.Ul([html.Li(_c) for _c in ix_cols]))
|
436
441
|
is_composite_item = "✅" if col else ""
|
437
|
-
ix_key_item = html.Pre(
|
442
|
+
ix_key_item = html.Pre(
|
443
|
+
INDEX_PREFIX_EMOJI.get(ix_key, '')
|
444
|
+
+ (' ' if ix_key in INDEX_PREFIX_EMOJI else '')
|
445
|
+
+ ix_key
|
446
|
+
)
|
438
447
|
indices_rows.append(
|
439
448
|
html.Tr([
|
440
449
|
html.Td(ix_key_item),
|
441
450
|
html.Td(col_item),
|
442
|
-
html.Td(html.Pre(ix_name)),
|
451
|
+
html.Td(html.Pre(ix_name or '')),
|
443
452
|
html.Td(is_composite_item),
|
444
453
|
])
|
445
454
|
)
|
meerschaum/api/routes/_pipes.py
CHANGED
@@ -558,7 +558,7 @@ def get_pipe_id(
|
|
558
558
|
curr_user = (
|
559
559
|
fastapi.Depends(manager) if not no_auth else None
|
560
560
|
),
|
561
|
-
) -> int:
|
561
|
+
) -> Union[int, str]:
|
562
562
|
"""
|
563
563
|
Get a Pipe's ID.
|
564
564
|
"""
|
@@ -573,36 +573,36 @@ def get_pipe_id(
|
|
573
573
|
tags = ['Pipes']
|
574
574
|
)
|
575
575
|
def get_pipe_attributes(
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
576
|
+
connector_keys: str,
|
577
|
+
metric_key: str,
|
578
|
+
location_key: str,
|
579
|
+
curr_user=(
|
580
|
+
fastapi.Depends(manager) if not no_auth else None
|
581
|
+
),
|
582
|
+
) -> Dict[str, Any]:
|
583
583
|
"""Get a Pipe's attributes."""
|
584
584
|
return get_pipe(connector_keys, metric_key, location_key).attributes
|
585
585
|
|
586
586
|
|
587
587
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/exists', tags=['Pipes'])
|
588
588
|
def get_pipe_exists(
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
589
|
+
connector_keys: str,
|
590
|
+
metric_key: str,
|
591
|
+
location_key: str,
|
592
|
+
curr_user = (
|
593
|
+
fastapi.Depends(manager) if not no_auth else None
|
594
|
+
),
|
595
|
+
) -> bool:
|
596
596
|
"""Determine whether a Pipe exists."""
|
597
597
|
return get_pipe(connector_keys, metric_key, location_key).exists()
|
598
598
|
|
599
599
|
|
600
600
|
@app.post(endpoints['metadata'], tags=['Pipes'])
|
601
601
|
def create_metadata(
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
602
|
+
curr_user = (
|
603
|
+
fastapi.Depends(manager) if not no_auth else None
|
604
|
+
),
|
605
|
+
) -> bool:
|
606
606
|
"""Create Pipe metadata tables"""
|
607
607
|
from meerschaum.connectors.sql.tables import get_tables
|
608
608
|
try:
|
@@ -614,16 +614,16 @@ def create_metadata(
|
|
614
614
|
|
615
615
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/rowcount', tags=['Pipes'])
|
616
616
|
def get_pipe_rowcount(
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
617
|
+
connector_keys: str,
|
618
|
+
metric_key: str,
|
619
|
+
location_key: str,
|
620
|
+
begin: Union[str, int, None] = None,
|
621
|
+
end: Union[str, int, None] = None,
|
622
|
+
params: Optional[Dict[str, Any]] = None,
|
623
|
+
curr_user = (
|
624
|
+
fastapi.Depends(manager) if not no_auth else None
|
625
|
+
),
|
626
|
+
) -> int:
|
627
627
|
"""
|
628
628
|
Return a pipe's rowcount.
|
629
629
|
"""
|
@@ -632,10 +632,10 @@ def get_pipe_rowcount(
|
|
632
632
|
if is_int(end):
|
633
633
|
end = int(end)
|
634
634
|
return get_pipe(connector_keys, metric_key, location_key).get_rowcount(
|
635
|
-
begin
|
636
|
-
end
|
637
|
-
params
|
638
|
-
debug
|
635
|
+
begin=begin,
|
636
|
+
end=end,
|
637
|
+
params=params,
|
638
|
+
debug=debug,
|
639
639
|
)
|
640
640
|
|
641
641
|
|
@@ -644,13 +644,13 @@ def get_pipe_rowcount(
|
|
644
644
|
tags=['Pipes']
|
645
645
|
)
|
646
646
|
def get_pipe_columns_types(
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
647
|
+
connector_keys: str,
|
648
|
+
metric_key: str,
|
649
|
+
location_key: str,
|
650
|
+
curr_user=(
|
651
|
+
fastapi.Depends(manager) if not no_auth else None
|
652
|
+
),
|
653
|
+
) -> Dict[str, str]:
|
654
654
|
"""
|
655
655
|
Return a dictionary of column names and types.
|
656
656
|
|
@@ -663,3 +663,21 @@ def get_pipe_columns_types(
|
|
663
663
|
```
|
664
664
|
"""
|
665
665
|
return get_pipe(connector_keys, metric_key, location_key).dtypes
|
666
|
+
|
667
|
+
|
668
|
+
@app.get(
|
669
|
+
pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/columns/indices',
|
670
|
+
tags=['Pipes']
|
671
|
+
)
|
672
|
+
def get_pipe_columns_indices(
|
673
|
+
connector_keys: str,
|
674
|
+
metric_key: str,
|
675
|
+
location_key: str,
|
676
|
+
curr_user=(
|
677
|
+
fastapi.Depends(manager) if not no_auth else None
|
678
|
+
),
|
679
|
+
) -> Dict[str, List[Dict[str, str]]]:
|
680
|
+
"""
|
681
|
+
Return a dictionary of column names and related indices.
|
682
|
+
"""
|
683
|
+
return get_pipe(connector_keys, metric_key, location_key).get_columns_indices()
|
meerschaum/config/_edit.py
CHANGED
@@ -7,44 +7,71 @@ Functions for editing the configuration file
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
import sys
|
11
10
|
import pathlib
|
12
11
|
from meerschaum.utils.typing import Optional, Any, SuccessTuple, Mapping, Dict, List, Union
|
13
12
|
|
13
|
+
|
14
14
|
def edit_config(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
keys: Optional[List[str]] = None,
|
16
|
+
params: Optional[Dict[str, Any]] = None,
|
17
|
+
debug: bool = False,
|
18
|
+
**kw: Any
|
19
|
+
) -> SuccessTuple:
|
20
20
|
"""Edit the configuration files."""
|
21
21
|
from meerschaum.config import get_config, config
|
22
|
-
from meerschaum.config._read_config import get_keyfile_path
|
22
|
+
from meerschaum.config._read_config import get_keyfile_path, read_config
|
23
23
|
from meerschaum.config._paths import CONFIG_DIR_PATH
|
24
24
|
from meerschaum.utils.packages import reload_meerschaum
|
25
25
|
from meerschaum.utils.misc import edit_file
|
26
|
-
from meerschaum.utils.
|
26
|
+
from meerschaum.utils.warnings import warn, dprint
|
27
|
+
from meerschaum.utils.prompt import prompt
|
27
28
|
|
28
29
|
if keys is None:
|
29
30
|
keys = []
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
def _edit_key(key: str):
|
33
|
+
while True:
|
34
|
+
### If defined in default, create the config file.
|
35
|
+
key_config = config.pop(key, None)
|
36
|
+
keyfile_path = get_keyfile_path(key, create_new=True)
|
37
|
+
get_config(key, write_missing=True, warn=False)
|
38
|
+
|
39
|
+
edit_file(get_keyfile_path(key, create_new=True))
|
40
|
+
|
41
|
+
### TODO: verify that the file is valid. Retry if not.
|
42
|
+
try:
|
43
|
+
new_key_config = read_config(
|
44
|
+
CONFIG_DIR_PATH,
|
45
|
+
[key],
|
46
|
+
write_missing=False,
|
47
|
+
raise_parsing_errors=True,
|
48
|
+
)
|
49
|
+
except Exception:
|
50
|
+
if key_config:
|
51
|
+
config[key] = key_config
|
52
|
+
warn(f"Could not parse key '{key}'.", stack=False)
|
53
|
+
_ = prompt(f"Press [Enter] to edit '{keyfile_path}', [CTRL+C] to exit.")
|
54
|
+
continue
|
55
|
+
|
56
|
+
if new_key_config:
|
57
|
+
break
|
58
|
+
|
59
|
+
try:
|
60
|
+
for k in keys:
|
61
|
+
_edit_key(k)
|
62
|
+
except KeyboardInterrupt:
|
63
|
+
return False, f""
|
37
64
|
|
38
65
|
reload_meerschaum(debug=debug)
|
39
66
|
return (True, "Success")
|
40
67
|
|
41
68
|
|
42
69
|
def write_config(
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
70
|
+
config_dict: Optional[Dict[str, Any]] = None,
|
71
|
+
directory: Union[str, pathlib.Path, None] = None,
|
72
|
+
debug: bool = False,
|
73
|
+
**kw: Any
|
74
|
+
) -> bool:
|
48
75
|
"""Write YAML and JSON files to the configuration directory.
|
49
76
|
|
50
77
|
Parameters
|
@@ -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',
|