meerschaum 2.9.5__py3-none-any.whl → 3.0.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.
Files changed (153) hide show
  1. meerschaum/__init__.py +5 -2
  2. meerschaum/_internal/__init__.py +1 -0
  3. meerschaum/_internal/arguments/_parse_arguments.py +4 -4
  4. meerschaum/_internal/arguments/_parser.py +17 -1
  5. meerschaum/_internal/entry.py +6 -6
  6. meerschaum/_internal/shell/Shell.py +1 -1
  7. meerschaum/_internal/static.py +372 -0
  8. meerschaum/actions/api.py +12 -2
  9. meerschaum/actions/bootstrap.py +7 -7
  10. meerschaum/actions/edit.py +142 -18
  11. meerschaum/actions/register.py +137 -6
  12. meerschaum/actions/show.py +117 -29
  13. meerschaum/actions/stop.py +4 -1
  14. meerschaum/actions/sync.py +1 -1
  15. meerschaum/actions/tag.py +9 -8
  16. meerschaum/api/__init__.py +9 -2
  17. meerschaum/api/_events.py +39 -2
  18. meerschaum/api/_oauth2.py +118 -8
  19. meerschaum/api/_tokens.py +102 -0
  20. meerschaum/api/dash/__init__.py +0 -1
  21. meerschaum/api/dash/callbacks/custom.py +2 -2
  22. meerschaum/api/dash/callbacks/dashboard.py +102 -18
  23. meerschaum/api/dash/callbacks/plugins.py +0 -1
  24. meerschaum/api/dash/callbacks/register.py +1 -1
  25. meerschaum/api/dash/callbacks/settings/__init__.py +1 -0
  26. meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
  27. meerschaum/api/dash/callbacks/settings/tokens.py +388 -0
  28. meerschaum/api/dash/components.py +30 -8
  29. meerschaum/api/dash/keys.py +19 -93
  30. meerschaum/api/dash/pages/dashboard.py +1 -20
  31. meerschaum/api/dash/pages/settings/__init__.py +1 -0
  32. meerschaum/api/dash/pages/settings/password_reset.py +1 -1
  33. meerschaum/api/dash/pages/settings/tokens.py +55 -0
  34. meerschaum/api/dash/pipes.py +94 -59
  35. meerschaum/api/dash/sessions.py +12 -0
  36. meerschaum/api/dash/tokens.py +606 -0
  37. meerschaum/api/dash/websockets.py +1 -1
  38. meerschaum/api/dash/webterm.py +4 -0
  39. meerschaum/api/models/__init__.py +23 -3
  40. meerschaum/api/models/_actions.py +22 -0
  41. meerschaum/api/models/_pipes.py +85 -7
  42. meerschaum/api/models/_tokens.py +81 -0
  43. meerschaum/api/resources/templates/termpage.html +12 -0
  44. meerschaum/api/routes/__init__.py +1 -0
  45. meerschaum/api/routes/_actions.py +3 -4
  46. meerschaum/api/routes/_connectors.py +3 -7
  47. meerschaum/api/routes/_jobs.py +14 -35
  48. meerschaum/api/routes/_login.py +49 -12
  49. meerschaum/api/routes/_misc.py +5 -10
  50. meerschaum/api/routes/_pipes.py +134 -111
  51. meerschaum/api/routes/_plugins.py +38 -28
  52. meerschaum/api/routes/_tokens.py +236 -0
  53. meerschaum/api/routes/_users.py +47 -35
  54. meerschaum/api/routes/_version.py +3 -3
  55. meerschaum/config/__init__.py +43 -20
  56. meerschaum/config/_default.py +32 -5
  57. meerschaum/config/_edit.py +28 -24
  58. meerschaum/config/_environment.py +1 -1
  59. meerschaum/config/_patch.py +6 -6
  60. meerschaum/config/_paths.py +5 -1
  61. meerschaum/config/_read_config.py +65 -34
  62. meerschaum/config/_sync.py +6 -3
  63. meerschaum/config/_version.py +1 -1
  64. meerschaum/config/stack/__init__.py +24 -5
  65. meerschaum/config/static.py +18 -0
  66. meerschaum/connectors/_Connector.py +10 -4
  67. meerschaum/connectors/__init__.py +4 -20
  68. meerschaum/connectors/api/_APIConnector.py +34 -6
  69. meerschaum/connectors/api/_actions.py +2 -2
  70. meerschaum/connectors/api/_jobs.py +1 -1
  71. meerschaum/connectors/api/_login.py +33 -7
  72. meerschaum/connectors/api/_misc.py +2 -2
  73. meerschaum/connectors/api/_pipes.py +15 -14
  74. meerschaum/connectors/api/_plugins.py +2 -2
  75. meerschaum/connectors/api/_request.py +1 -1
  76. meerschaum/connectors/api/_tokens.py +146 -0
  77. meerschaum/connectors/api/_users.py +70 -58
  78. meerschaum/connectors/instance/_InstanceConnector.py +83 -0
  79. meerschaum/connectors/instance/__init__.py +10 -0
  80. meerschaum/connectors/instance/_pipes.py +442 -0
  81. meerschaum/connectors/instance/_plugins.py +151 -0
  82. meerschaum/connectors/instance/_tokens.py +296 -0
  83. meerschaum/connectors/instance/_users.py +181 -0
  84. meerschaum/connectors/parse.py +4 -1
  85. meerschaum/connectors/sql/_SQLConnector.py +8 -5
  86. meerschaum/connectors/sql/_cli.py +12 -11
  87. meerschaum/connectors/sql/_create_engine.py +6 -154
  88. meerschaum/connectors/sql/_fetch.py +2 -18
  89. meerschaum/connectors/sql/_pipes.py +42 -31
  90. meerschaum/connectors/sql/_plugins.py +29 -0
  91. meerschaum/connectors/sql/_sql.py +8 -1
  92. meerschaum/connectors/sql/_users.py +29 -2
  93. meerschaum/connectors/sql/tables/__init__.py +1 -1
  94. meerschaum/connectors/valkey/_ValkeyConnector.py +2 -4
  95. meerschaum/connectors/valkey/_pipes.py +9 -10
  96. meerschaum/connectors/valkey/_plugins.py +2 -26
  97. meerschaum/core/Pipe/__init__.py +31 -14
  98. meerschaum/core/Pipe/_attributes.py +156 -58
  99. meerschaum/core/Pipe/_bootstrap.py +54 -24
  100. meerschaum/core/Pipe/_data.py +41 -1
  101. meerschaum/core/Pipe/_dtypes.py +29 -14
  102. meerschaum/core/Pipe/_edit.py +12 -4
  103. meerschaum/core/Pipe/_show.py +5 -5
  104. meerschaum/core/Pipe/_sync.py +48 -53
  105. meerschaum/core/Pipe/_verify.py +1 -1
  106. meerschaum/{plugins → core/Plugin}/_Plugin.py +9 -11
  107. meerschaum/core/Plugin/__init__.py +1 -1
  108. meerschaum/core/Token/_Token.py +221 -0
  109. meerschaum/core/Token/__init__.py +12 -0
  110. meerschaum/core/User/_User.py +34 -8
  111. meerschaum/core/User/__init__.py +9 -1
  112. meerschaum/core/__init__.py +1 -0
  113. meerschaum/jobs/_Job.py +3 -2
  114. meerschaum/jobs/__init__.py +3 -2
  115. meerschaum/jobs/systemd.py +1 -1
  116. meerschaum/models/__init__.py +35 -0
  117. meerschaum/models/pipes.py +247 -0
  118. meerschaum/models/tokens.py +38 -0
  119. meerschaum/models/users.py +26 -0
  120. meerschaum/plugins/__init__.py +22 -7
  121. meerschaum/plugins/bootstrap.py +2 -1
  122. meerschaum/utils/_get_pipes.py +68 -27
  123. meerschaum/utils/daemon/Daemon.py +2 -1
  124. meerschaum/utils/daemon/__init__.py +30 -2
  125. meerschaum/utils/dataframe.py +95 -14
  126. meerschaum/utils/dtypes/__init__.py +91 -18
  127. meerschaum/utils/dtypes/sql.py +44 -0
  128. meerschaum/utils/formatting/__init__.py +1 -1
  129. meerschaum/utils/formatting/_pipes.py +5 -4
  130. meerschaum/utils/formatting/_shell.py +11 -9
  131. meerschaum/utils/misc.py +237 -80
  132. meerschaum/utils/packages/__init__.py +3 -6
  133. meerschaum/utils/packages/_packages.py +34 -32
  134. meerschaum/utils/pipes.py +181 -0
  135. meerschaum/utils/process.py +1 -1
  136. meerschaum/utils/prompt.py +3 -1
  137. meerschaum/utils/schedule.py +1 -0
  138. meerschaum/utils/sql.py +114 -37
  139. meerschaum/utils/typing.py +1 -4
  140. meerschaum/utils/venv/_Venv.py +2 -2
  141. meerschaum/utils/venv/__init__.py +5 -7
  142. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/METADATA +88 -80
  143. meerschaum-3.0.0rc1.dist-info/RECORD +282 -0
  144. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/WHEEL +1 -1
  145. meerschaum/api/models/_interfaces.py +0 -15
  146. meerschaum/api/models/_locations.py +0 -15
  147. meerschaum/api/models/_metrics.py +0 -15
  148. meerschaum/config/static/__init__.py +0 -186
  149. meerschaum-2.9.5.dist-info/RECORD +0 -263
  150. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/entry_points.txt +0 -0
  151. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/licenses/LICENSE +0 -0
  152. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/top_level.txt +0 -0
  153. {meerschaum-2.9.5.dist-info → meerschaum-3.0.0rc1.dist-info}/zip-safe +0 -0
@@ -0,0 +1,181 @@
1
+ #! /usr/bin/env python3
2
+ # vim:fenc=utf-8
3
+
4
+ """
5
+ Define utilities for working with pipes.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Callable
11
+ import re
12
+ import json
13
+ import ast
14
+ import copy
15
+ import uuid
16
+
17
+ from meerschaum.utils.typing import PipesDict, Optional, Any
18
+ import meerschaum as mrsm
19
+
20
+
21
+ def evaluate_pipe_access_chain(access_chain: str, pipe: mrsm.Pipe):
22
+ """
23
+ Safely evaluate the access chain on a Pipe.
24
+ """
25
+ expr = f"pipe{access_chain}"
26
+ tree = ast.parse(expr, mode='eval')
27
+
28
+ def _eval(node, context):
29
+ if isinstance(node, ast.Expression):
30
+ return _eval(node.body, context)
31
+
32
+ elif isinstance(node, ast.Name):
33
+ if node.id == "pipe":
34
+ return context
35
+ raise ValueError(f"Unknown variable: {node.id}")
36
+
37
+ elif isinstance(node, ast.Attribute):
38
+ value = _eval(node.value, context)
39
+ return getattr(value, node.attr)
40
+
41
+ elif isinstance(node, ast.Subscript):
42
+ value = _eval(node.value, context)
43
+ key = _eval(node.slice, context) if isinstance(node.slice, ast.Index) else _eval(node.slice, context)
44
+ return value[key]
45
+
46
+ elif isinstance(node, ast.Constant): # Python 3.8+
47
+ return node.value
48
+
49
+ elif isinstance(node, ast.Str): # Older Python
50
+ return node.s
51
+
52
+ elif isinstance(node, ast.Index): # Older Python AST style
53
+ return _eval(node.value, context)
54
+
55
+ else:
56
+ raise TypeError(f"Unsupported AST node: {ast.dump(node)}")
57
+
58
+ return _eval(tree, pipe)
59
+
60
+
61
+
62
+ def _evaluate_pipe_access_chain_from_match(pipe_match: re.Match) -> Any:
63
+ """
64
+ Helper function to evaluate a pipe from a regex match object.
65
+ """
66
+ from meerschaum.utils.warnings import warn
67
+ from meerschaum.utils.misc import parse_arguments_str
68
+ from meerschaum.utils.sql import sql_item_name
69
+ try:
70
+ args_str = pipe_match.group(1)
71
+ access_chain = pipe_match.group(2)
72
+ args, kwargs = parse_arguments_str(args_str)
73
+ pipe = mrsm.Pipe(*args, **kwargs)
74
+ except Exception as e:
75
+ warn(f"Failed to parse pipe from template string:\n{e}")
76
+ raise e
77
+
78
+ if not access_chain:
79
+ target = pipe.target
80
+ schema = (
81
+ pipe.instance_connector.get_pipe_schema(pipe)
82
+ if hasattr(pipe.instance_connector, 'get_pipe_schema')
83
+ else None
84
+ )
85
+ return (
86
+ sql_item_name(target, pipe.instance_connector.flavor, schema)
87
+ if pipe.instance_connector.type == 'sql'
88
+ else pipe.target
89
+ )
90
+
91
+ return evaluate_pipe_access_chain(access_chain, pipe)
92
+
93
+
94
+ def replace_pipes_syntax(text: str) -> Any:
95
+ """
96
+ Parse a string containing the `{{ Pipe() }}` syntax.
97
+ """
98
+ from meerschaum.utils.warnings import warn
99
+ from meerschaum.utils.sql import sql_item_name
100
+ from meerschaum.utils.dtypes import json_serialize_value
101
+ from meerschaum.utils.misc import parse_arguments_str
102
+ pattern = r'\{\{\s*(?:mrsm\.)?Pipe\((.*?)\)((?:\.[\w]+|\[[^\]]+\])*)\s*\}\}'
103
+
104
+ matches = list(re.finditer(pattern, text))
105
+ if not matches:
106
+ return text
107
+
108
+ placeholders = {}
109
+ for match in matches:
110
+ placeholder = f"__mrsm_pipe_placeholder_{uuid.uuid4().hex}__"
111
+ placeholders[placeholder] = match
112
+
113
+ substituted_text = text
114
+ for placeholder, match in placeholders.items():
115
+ substituted_text = substituted_text.replace(match.group(0), placeholder)
116
+
117
+ resolved_values = {}
118
+ for placeholder, match in placeholders.items():
119
+ try:
120
+ resolved_values[placeholder] = _evaluate_pipe_access_chain_from_match(match)
121
+ except Exception as e:
122
+ warn(f"Failed to resolve pipe syntax '{match.group(0)}': {e}")
123
+ resolved_values[placeholder] = match.group(0)
124
+
125
+ if len(matches) == 1:
126
+ match = matches[0]
127
+ placeholder = list(placeholders.keys())[0]
128
+ if text.strip() == match.group(0):
129
+ return resolved_values[placeholder]
130
+
131
+ final_text = substituted_text
132
+ for placeholder, value in resolved_values.items():
133
+ if isinstance(value, (dict, list, bool, int, float)) or value is None:
134
+ final_text = final_text.replace(placeholder, json.dumps(value, default=json_serialize_value))
135
+ else:
136
+ final_text = final_text.replace(placeholder, str(value))
137
+
138
+ return final_text
139
+
140
+
141
+ def replace_pipes_in_dict(
142
+ pipes: Optional[PipesDict] = None,
143
+ func: Callable[[Any], Any] = str,
144
+ debug: bool = False,
145
+ **kw
146
+ ) -> PipesDict:
147
+ """
148
+ Replace the Pipes in a Pipes dict with the result of another function.
149
+
150
+ Parameters
151
+ ----------
152
+ pipes: Optional[PipesDict], default None
153
+ The pipes dict to be processed.
154
+
155
+ func: Callable[[Any], Any], default str
156
+ The function to be applied to every pipe.
157
+ Defaults to the string constructor.
158
+
159
+ debug: bool, default False
160
+ Verbosity toggle.
161
+
162
+
163
+ Returns
164
+ -------
165
+ A dictionary where every pipe is replaced with the output of a function.
166
+
167
+ """
168
+ def change_dict(d : Dict[Any, Any], func : 'function') -> None:
169
+ for k, v in d.items():
170
+ if isinstance(v, dict):
171
+ change_dict(v, func)
172
+ else:
173
+ d[k] = func(v)
174
+
175
+ if pipes is None:
176
+ from meerschaum import get_pipes
177
+ pipes = get_pipes(debug=debug, **kw)
178
+
179
+ result = copy.deepcopy(pipes)
180
+ change_dict(result, func)
181
+ return result
@@ -18,7 +18,7 @@ import platform
18
18
 
19
19
  import meerschaum as mrsm
20
20
  from meerschaum.utils.typing import Union, Optional, Any, Callable, Dict, Tuple
21
- from meerschaum.config.static import STATIC_CONFIG
21
+ from meerschaum._internal.static import STATIC_CONFIG
22
22
 
23
23
  _child_processes = []
24
24
  def signal_handler(sig, frame):
@@ -399,6 +399,8 @@ def choose(
399
399
  noask = noask,
400
400
  **kw
401
401
  )
402
+ if not answer:
403
+ continue
402
404
  ### Split along the delimiter.
403
405
  _answers = [answer] if not multiple else [a for a in answer.split(delimiter)]
404
406
 
@@ -564,7 +566,7 @@ def check_noask(noask: bool = False) -> bool:
564
566
  """
565
567
  Flip `noask` to `True` if `MRSM_NOASK` is set.
566
568
  """
567
- from meerschaum.config.static import STATIC_CONFIG
569
+ from meerschaum._internal.static import STATIC_CONFIG
568
570
  NOASK = STATIC_CONFIG['environment']['noask']
569
571
  if noask:
570
572
  return True
@@ -14,6 +14,7 @@ import meerschaum as mrsm
14
14
  from meerschaum.utils.typing import Callable, Any, Optional, List, Dict
15
15
  from meerschaum.utils.warnings import warn, error
16
16
 
17
+
17
18
  STARTING_KEYWORD: str = 'starting'
18
19
  INTERVAL_UNITS: List[str] = ['months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'years']
19
20
  FREQUENCY_ALIASES: Dict[str, str] = {
meerschaum/utils/sql.py CHANGED
@@ -41,13 +41,33 @@ version_queries = {
41
41
  }
42
42
  SKIP_IF_EXISTS_FLAVORS = {'mssql', 'oracle'}
43
43
  DROP_IF_EXISTS_FLAVORS = {
44
- 'timescaledb', 'postgresql', 'postgis', 'citus', 'mssql', 'mysql', 'mariadb', 'sqlite',
44
+ 'timescaledb',
45
+ 'timescaledb-ha',
46
+ 'postgresql',
47
+ 'postgis',
48
+ 'citus',
49
+ 'mssql',
50
+ 'mysql',
51
+ 'mariadb',
52
+ 'sqlite',
45
53
  }
46
54
  DROP_INDEX_IF_EXISTS_FLAVORS = {
47
- 'mssql', 'timescaledb', 'postgresql', 'postgis', 'sqlite', 'citus',
55
+ 'mssql',
56
+ 'timescaledb',
57
+ 'timescaledb-ha',
58
+ 'postgresql',
59
+ 'postgis',
60
+ 'sqlite',
61
+ 'citus',
48
62
  }
49
63
  SKIP_AUTO_INCREMENT_FLAVORS = {'citus', 'duckdb'}
50
- COALESCE_UNIQUE_INDEX_FLAVORS = {'timescaledb', 'postgresql', 'postgis', 'citus'}
64
+ COALESCE_UNIQUE_INDEX_FLAVORS = {
65
+ 'timescaledb',
66
+ 'timescaledb-ha',
67
+ 'postgresql',
68
+ 'postgis',
69
+ 'citus',
70
+ }
51
71
  UPDATE_QUERIES = {
52
72
  'default': """
53
73
  UPDATE {target_table_name} AS f
@@ -67,6 +87,12 @@ UPDATE_QUERIES = {
67
87
  FROM {patch_table_name}
68
88
  ON CONFLICT ({join_cols_str}) DO {update_or_nothing} {sets_subquery_none_excluded}
69
89
  """,
90
+ 'timescaledb-ha-upsert': """
91
+ INSERT INTO {target_table_name} ({patch_cols_str})
92
+ SELECT {patch_cols_str}
93
+ FROM {patch_table_name}
94
+ ON CONFLICT ({join_cols_str}) DO {update_or_nothing} {sets_subquery_none_excluded}
95
+ """,
70
96
  'postgresql-upsert': """
71
97
  INSERT INTO {target_table_name} ({patch_cols_str})
72
98
  SELECT {patch_cols_str}
@@ -286,6 +312,7 @@ columns_types_queries = {
286
312
  }
287
313
  hypertable_queries = {
288
314
  'timescaledb': 'SELECT hypertable_size(\'{table_name}\')',
315
+ 'timescaledb-ha': 'SELECT hypertable_size(\'{table_name}\')',
289
316
  'citus': 'SELECT citus_table_size(\'{table_name}\')',
290
317
  }
291
318
  columns_indices_queries = {
@@ -483,49 +510,83 @@ reset_autoincrement_queries: Dict[str, Union[str, List[str]]] = {
483
510
  ),
484
511
  }
485
512
  table_wrappers = {
486
- 'default' : ('"', '"'),
487
- 'timescaledb': ('"', '"'),
488
- 'citus' : ('"', '"'),
489
- 'duckdb' : ('"', '"'),
490
- 'postgresql' : ('"', '"'),
491
- 'postgis' : ('"', '"'),
492
- 'sqlite' : ('"', '"'),
493
- 'mysql' : ('`', '`'),
494
- 'mariadb' : ('`', '`'),
495
- 'mssql' : ('[', ']'),
496
- 'cockroachdb': ('"', '"'),
497
- 'oracle' : ('"', '"'),
513
+ 'default' : ('"', '"'),
514
+ 'timescaledb' : ('"', '"'),
515
+ 'timescaledb-ha': ('"', '"'),
516
+ 'citus' : ('"', '"'),
517
+ 'duckdb' : ('"', '"'),
518
+ 'postgresql' : ('"', '"'),
519
+ 'postgis' : ('"', '"'),
520
+ 'sqlite' : ('"', '"'),
521
+ 'mysql' : ('`', '`'),
522
+ 'mariadb' : ('`', '`'),
523
+ 'mssql' : ('[', ']'),
524
+ 'cockroachdb' : ('"', '"'),
525
+ 'oracle' : ('"', '"'),
498
526
  }
499
527
  max_name_lens = {
500
- 'default' : 64,
501
- 'mssql' : 128,
502
- 'oracle' : 30,
503
- 'postgresql' : 64,
504
- 'postgis' : 64,
505
- 'timescaledb': 64,
506
- 'citus' : 64,
507
- 'cockroachdb': 64,
508
- 'sqlite' : 1024, ### Probably more, but 1024 seems more than reasonable.
509
- 'mysql' : 64,
510
- 'mariadb' : 64,
528
+ 'default' : 64,
529
+ 'mssql' : 128,
530
+ 'oracle' : 30,
531
+ 'postgresql' : 64,
532
+ 'postgis' : 64,
533
+ 'timescaledb' : 64,
534
+ 'timescaledb-ha': 64,
535
+ 'citus' : 64,
536
+ 'cockroachdb' : 64,
537
+ 'sqlite' : 1024, ### Probably more, but 1024 seems more than reasonable.
538
+ 'mysql' : 64,
539
+ 'mariadb' : 64,
540
+ }
541
+ json_flavors = {
542
+ 'postgresql',
543
+ 'postgis',
544
+ 'timescaledb',
545
+ 'timescaledb-ha',
546
+ 'citus',
547
+ 'cockroachdb',
548
+ }
549
+ NO_SCHEMA_FLAVORS = {
550
+ 'oracle',
551
+ 'sqlite',
552
+ 'mysql',
553
+ 'mariadb',
554
+ 'duckdb',
511
555
  }
512
- json_flavors = {'postgresql', 'postgis', 'timescaledb', 'citus', 'cockroachdb'}
513
- NO_SCHEMA_FLAVORS = {'oracle', 'sqlite', 'mysql', 'mariadb', 'duckdb'}
514
556
  DEFAULT_SCHEMA_FLAVORS = {
515
557
  'postgresql': 'public',
516
558
  'postgis': 'public',
517
559
  'timescaledb': 'public',
560
+ 'timescaledb-ha': 'public',
518
561
  'citus': 'public',
519
562
  'cockroachdb': 'public',
520
563
  'mysql': 'mysql',
521
564
  'mariadb': 'mysql',
522
565
  'mssql': 'dbo',
523
566
  }
524
- OMIT_NULLSFIRST_FLAVORS = {'mariadb', 'mysql', 'mssql'}
567
+ OMIT_NULLSFIRST_FLAVORS = {
568
+ 'mariadb',
569
+ 'mysql',
570
+ 'mssql',
571
+ }
525
572
 
526
- SINGLE_ALTER_TABLE_FLAVORS = {'duckdb', 'sqlite', 'mssql', 'oracle'}
527
- NO_CTE_FLAVORS = {'mysql', 'mariadb'}
528
- NO_SELECT_INTO_FLAVORS = {'sqlite', 'oracle', 'mysql', 'mariadb', 'duckdb'}
573
+ SINGLE_ALTER_TABLE_FLAVORS = {
574
+ 'duckdb',
575
+ 'sqlite',
576
+ 'mssql',
577
+ 'oracle',
578
+ }
579
+ NO_CTE_FLAVORS = {
580
+ 'mysql',
581
+ 'mariadb',
582
+ }
583
+ NO_SELECT_INTO_FLAVORS = {
584
+ 'sqlite',
585
+ 'oracle',
586
+ 'mysql',
587
+ 'mariadb',
588
+ 'duckdb',
589
+ }
529
590
 
530
591
 
531
592
  def clean(substring: str) -> None:
@@ -560,6 +621,7 @@ def dateadd_str(
560
621
  - `'postgresql'`
561
622
  - `'postgis'`
562
623
  - `'timescaledb'`
624
+ - `'timescaledb-ha'`
563
625
  - `'citus'`
564
626
  - `'cockroachdb'`
565
627
  - `'duckdb'`
@@ -663,7 +725,14 @@ def dateadd_str(
663
725
  )
664
726
 
665
727
  da = ""
666
- if flavor in ('postgresql', 'postgis', 'timescaledb', 'cockroachdb', 'citus'):
728
+ if flavor in (
729
+ 'postgresql',
730
+ 'postgis',
731
+ 'timescaledb',
732
+ 'timescaledb-ha',
733
+ 'cockroachdb',
734
+ 'citus',
735
+ ):
667
736
  begin = (
668
737
  f"CAST({begin} AS {db_type})" if begin != 'now'
669
738
  else f"CAST(NOW() AT TIME ZONE 'utc' AS {db_type})"
@@ -969,7 +1038,7 @@ def build_where(
969
1038
  ```
970
1039
  """
971
1040
  import json
972
- from meerschaum.config.static import STATIC_CONFIG
1041
+ from meerschaum._internal.static import STATIC_CONFIG
973
1042
  from meerschaum.utils.warnings import warn
974
1043
  from meerschaum.utils.dtypes import value_is_null, none_if_null
975
1044
  negation_prefix = STATIC_CONFIG['system']['fetch_pipes_keys']['negation_prefix']
@@ -2112,7 +2181,11 @@ def _get_create_table_query_from_dtypes(
2112
2181
  )
2113
2182
  elif flavor == 'oracle':
2114
2183
  query += f"\n {col_name} {col_db_type} {auto_increment_str} PRIMARY KEY,"
2115
- elif flavor == 'timescaledb' and datetime_column and datetime_column != primary_key:
2184
+ elif (
2185
+ flavor in ('timescaledb', 'timescaledb-ha')
2186
+ and datetime_column
2187
+ and datetime_column != primary_key
2188
+ ):
2116
2189
  query += f"\n {col_name} {col_db_type}{auto_increment_str} NOT NULL,"
2117
2190
  elif flavor == 'mssql':
2118
2191
  query += f"\n {col_name} {col_db_type}{auto_increment_str} NOT NULL,"
@@ -2125,7 +2198,7 @@ def _get_create_table_query_from_dtypes(
2125
2198
  col_name = sql_item_name(col, schema=None, flavor=flavor)
2126
2199
  query += f"\n {col_name} {db_type},"
2127
2200
  if (
2128
- flavor == 'timescaledb'
2201
+ flavor in ('timescaledb', 'timescaledb-ha')
2129
2202
  and datetime_column
2130
2203
  and primary_key
2131
2204
  and datetime_column != primary_key
@@ -2248,7 +2321,11 @@ def _get_create_table_query_from_cte(
2248
2321
  "ADD PRIMARY KEY ({primary_key_name})"
2249
2322
  ),
2250
2323
  ]
2251
- elif flavor == 'timescaledb' and datetime_column and datetime_column != primary_key:
2324
+ elif (
2325
+ flavor in ('timescaledb', 'timescaledb-ha')
2326
+ and datetime_column
2327
+ and datetime_column != primary_key
2328
+ ):
2252
2329
  create_table_queries = [
2253
2330
  (
2254
2331
  "SELECT *\n"
@@ -76,10 +76,7 @@ import collections.abc
76
76
  collections.Iterable = collections.abc.Iterable
77
77
 
78
78
  SuccessTuple = Tuple[bool, str]
79
- InstanceConnector = Union[
80
- 'meerschaum.connectors.sql.SQLConnector',
81
- 'meerschaum.connectors.api.APIConnector'
82
- ]
79
+ InstanceConnector = 'meerschaum.connectors.InstanceConnector'
83
80
  PipesDict = Dict[
84
81
  str, Dict[ ### connector_keys : metrics
85
82
  str, Dict[ ### metric_key : locations
@@ -35,13 +35,13 @@ class Venv:
35
35
 
36
36
  def __init__(
37
37
  self,
38
- venv: Union[str, 'meerschaum.plugins.Plugin', None] = 'mrsm',
38
+ venv: Union[str, 'meerschaum.core.Plugin', None] = 'mrsm',
39
39
  debug: bool = False,
40
40
  ) -> None:
41
41
  from meerschaum.utils.venv import activate_venv, deactivate_venv, active_venvs
42
42
  ### For some weird threading issue,
43
43
  ### we can't use `isinstance` here.
44
- if 'meerschaum.plugins._Plugin' in str(type(venv)):
44
+ if '_Plugin' in str(type(venv)):
45
45
  self._venv = venv.name
46
46
  self._activate = venv.activate_venv
47
47
  self._deactivate = venv.deactivate_venv
@@ -8,6 +8,8 @@ Manage virtual environments.
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
+ import pathlib
12
+
11
13
  from meerschaum.utils.typing import Optional, Union, Dict, List, Tuple
12
14
  from meerschaum.utils.threading import RLock, get_ident
13
15
 
@@ -229,7 +231,6 @@ def verify_venv(
229
231
  """
230
232
  Verify that the virtual environment matches the expected state.
231
233
  """
232
- import pathlib
233
234
  import platform
234
235
  import os
235
236
  import shutil
@@ -382,11 +383,10 @@ def init_venv(
382
383
  import sys
383
384
  import platform
384
385
  import os
385
- import pathlib
386
386
  import shutil
387
387
  import time
388
388
 
389
- from meerschaum.config.static import STATIC_CONFIG
389
+ from meerschaum._internal.static import STATIC_CONFIG
390
390
  from meerschaum.config._paths import (
391
391
  VIRTENV_RESOURCES_PATH,
392
392
  VENVS_CACHE_RESOURCES_PATH,
@@ -682,7 +682,7 @@ def venv_target_path(
682
682
  venv: Union[str, None],
683
683
  allow_nonexistent: bool = False,
684
684
  debug: bool = False,
685
- ) -> 'pathlib.Path':
685
+ ) -> pathlib.Path:
686
686
  """
687
687
  Return a virtual environment's site-package path.
688
688
 
@@ -702,10 +702,9 @@ def venv_target_path(
702
702
  import os
703
703
  import sys
704
704
  import platform
705
- import pathlib
706
705
  import site
707
706
  from meerschaum.config._paths import VIRTENV_RESOURCES_PATH
708
- from meerschaum.config.static import STATIC_CONFIG
707
+ from meerschaum._internal.static import STATIC_CONFIG
709
708
 
710
709
  ### Check sys.path for a user-writable site-packages directory.
711
710
  if venv is None:
@@ -839,7 +838,6 @@ def get_module_venv(module) -> Union[str, None]:
839
838
  -------
840
839
  The name of a venv or `None`.
841
840
  """
842
- import pathlib
843
841
  from meerschaum.config.paths import VIRTENV_RESOURCES_PATH
844
842
  module_path = pathlib.Path(module.__file__).resolve()
845
843
  try: